Initial Commit
This commit is contained in:
107
database/perl/lib/Test/Builder/Formatter.pm
Normal file
107
database/perl/lib/Test/Builder/Formatter.pm
Normal file
@@ -0,0 +1,107 @@
|
||||
package Test::Builder::Formatter;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '1.302183';
|
||||
|
||||
BEGIN { require Test2::Formatter::TAP; our @ISA = qw(Test2::Formatter::TAP) }
|
||||
|
||||
use Test2::Util::HashBase qw/no_header no_diag/;
|
||||
|
||||
BEGIN {
|
||||
*OUT_STD = Test2::Formatter::TAP->can('OUT_STD');
|
||||
*OUT_ERR = Test2::Formatter::TAP->can('OUT_ERR');
|
||||
|
||||
my $todo = OUT_ERR() + 1;
|
||||
*OUT_TODO = sub() { $todo };
|
||||
}
|
||||
|
||||
sub init {
|
||||
my $self = shift;
|
||||
$self->SUPER::init(@_);
|
||||
$self->{+HANDLES}->[OUT_TODO] = $self->{+HANDLES}->[OUT_STD];
|
||||
}
|
||||
|
||||
sub plan_tap {
|
||||
my ($self, $f) = @_;
|
||||
|
||||
return if $self->{+NO_HEADER};
|
||||
return $self->SUPER::plan_tap($f);
|
||||
}
|
||||
|
||||
sub debug_tap {
|
||||
my ($self, $f, $num) = @_;
|
||||
return if $self->{+NO_DIAG};
|
||||
my @out = $self->SUPER::debug_tap($f, $num);
|
||||
$self->redirect(\@out) if @out && ref $f->{about} && defined $f->{about}->{package}
|
||||
&& $f->{about}->{package} eq 'Test::Builder::TodoDiag';
|
||||
return @out;
|
||||
}
|
||||
|
||||
sub info_tap {
|
||||
my ($self, $f) = @_;
|
||||
return if $self->{+NO_DIAG};
|
||||
my @out = $self->SUPER::info_tap($f);
|
||||
$self->redirect(\@out) if @out && ref $f->{about} && defined $f->{about}->{package}
|
||||
&& $f->{about}->{package} eq 'Test::Builder::TodoDiag';
|
||||
return @out;
|
||||
}
|
||||
|
||||
sub redirect {
|
||||
my ($self, $out) = @_;
|
||||
$_->[0] = OUT_TODO for @$out;
|
||||
}
|
||||
|
||||
sub no_subtest_space { 1 }
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Test::Builder::Formatter - Test::Builder subclass of Test2::Formatter::TAP
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This is what takes events and turns them into TAP.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use Test::Builder; # Loads Test::Builder::Formatter for you
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Test2 can be found at
|
||||
F<http://github.com/Test-More/test-more/>.
|
||||
|
||||
=head1 MAINTAINERS
|
||||
|
||||
=over 4
|
||||
|
||||
=item Chad Granum E<lt>exodist@cpan.orgE<gt>
|
||||
|
||||
=back
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
=over 4
|
||||
|
||||
=item Chad Granum E<lt>exodist@cpan.orgE<gt>
|
||||
|
||||
=back
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright 2020 Chad Granum E<lt>exodist@cpan.orgE<gt>.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the same terms as Perl itself.
|
||||
|
||||
See F<http://dev.perl.org/licenses/>
|
||||
|
||||
=cut
|
||||
659
database/perl/lib/Test/Builder/IO/Scalar.pm
Normal file
659
database/perl/lib/Test/Builder/IO/Scalar.pm
Normal file
@@ -0,0 +1,659 @@
|
||||
package Test::Builder::IO::Scalar;
|
||||
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Test::Builder::IO::Scalar - A copy of IO::Scalar for Test::Builder
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This is a copy of L<IO::Scalar> which ships with L<Test::Builder> to
|
||||
support scalar references as filehandles on Perl 5.6. Newer
|
||||
versions of Perl simply use C<open()>'s built in support.
|
||||
|
||||
L<Test::Builder> can not have dependencies on other modules without
|
||||
careful consideration, so its simply been copied into the distribution.
|
||||
|
||||
=head1 COPYRIGHT and LICENSE
|
||||
|
||||
This file came from the "IO-stringy" Perl5 toolkit.
|
||||
|
||||
Copyright (c) 1996 by Eryq. All rights reserved.
|
||||
Copyright (c) 1999,2001 by ZeeGee Software Inc. All rights reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the same terms as Perl itself.
|
||||
|
||||
|
||||
=cut
|
||||
|
||||
# This is copied code, I don't care.
|
||||
##no critic
|
||||
|
||||
use Carp;
|
||||
use strict;
|
||||
use vars qw($VERSION @ISA);
|
||||
use IO::Handle;
|
||||
|
||||
use 5.005;
|
||||
|
||||
### The package version, both in 1.23 style *and* usable by MakeMaker:
|
||||
$VERSION = "2.114";
|
||||
|
||||
### Inheritance:
|
||||
@ISA = qw(IO::Handle);
|
||||
|
||||
#==============================
|
||||
|
||||
=head2 Construction
|
||||
|
||||
=over 4
|
||||
|
||||
=cut
|
||||
|
||||
#------------------------------
|
||||
|
||||
=item new [ARGS...]
|
||||
|
||||
I<Class method.>
|
||||
Return a new, unattached scalar handle.
|
||||
If any arguments are given, they're sent to open().
|
||||
|
||||
=cut
|
||||
|
||||
sub new {
|
||||
my $proto = shift;
|
||||
my $class = ref($proto) || $proto;
|
||||
my $self = bless \do { local *FH }, $class;
|
||||
tie *$self, $class, $self;
|
||||
$self->open(@_); ### open on anonymous by default
|
||||
$self;
|
||||
}
|
||||
sub DESTROY {
|
||||
shift->close;
|
||||
}
|
||||
|
||||
#------------------------------
|
||||
|
||||
=item open [SCALARREF]
|
||||
|
||||
I<Instance method.>
|
||||
Open the scalar handle on a new scalar, pointed to by SCALARREF.
|
||||
If no SCALARREF is given, a "private" scalar is created to hold
|
||||
the file data.
|
||||
|
||||
Returns the self object on success, undefined on error.
|
||||
|
||||
=cut
|
||||
|
||||
sub open {
|
||||
my ($self, $sref) = @_;
|
||||
|
||||
### Sanity:
|
||||
defined($sref) or do {my $s = ''; $sref = \$s};
|
||||
(ref($sref) eq "SCALAR") or croak "open() needs a ref to a scalar";
|
||||
|
||||
### Setup:
|
||||
*$self->{Pos} = 0; ### seek position
|
||||
*$self->{SR} = $sref; ### scalar reference
|
||||
$self;
|
||||
}
|
||||
|
||||
#------------------------------
|
||||
|
||||
=item opened
|
||||
|
||||
I<Instance method.>
|
||||
Is the scalar handle opened on something?
|
||||
|
||||
=cut
|
||||
|
||||
sub opened {
|
||||
*{shift()}->{SR};
|
||||
}
|
||||
|
||||
#------------------------------
|
||||
|
||||
=item close
|
||||
|
||||
I<Instance method.>
|
||||
Disassociate the scalar handle from its underlying scalar.
|
||||
Done automatically on destroy.
|
||||
|
||||
=cut
|
||||
|
||||
sub close {
|
||||
my $self = shift;
|
||||
%{*$self} = ();
|
||||
1;
|
||||
}
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
|
||||
#==============================
|
||||
|
||||
=head2 Input and output
|
||||
|
||||
=over 4
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
#------------------------------
|
||||
|
||||
=item flush
|
||||
|
||||
I<Instance method.>
|
||||
No-op, provided for OO compatibility.
|
||||
|
||||
=cut
|
||||
|
||||
sub flush { "0 but true" }
|
||||
|
||||
#------------------------------
|
||||
|
||||
=item getc
|
||||
|
||||
I<Instance method.>
|
||||
Return the next character, or undef if none remain.
|
||||
|
||||
=cut
|
||||
|
||||
sub getc {
|
||||
my $self = shift;
|
||||
|
||||
### Return undef right away if at EOF; else, move pos forward:
|
||||
return undef if $self->eof;
|
||||
substr(${*$self->{SR}}, *$self->{Pos}++, 1);
|
||||
}
|
||||
|
||||
#------------------------------
|
||||
|
||||
=item getline
|
||||
|
||||
I<Instance method.>
|
||||
Return the next line, or undef on end of string.
|
||||
Can safely be called in an array context.
|
||||
Currently, lines are delimited by "\n".
|
||||
|
||||
=cut
|
||||
|
||||
sub getline {
|
||||
my $self = shift;
|
||||
|
||||
### Return undef right away if at EOF:
|
||||
return undef if $self->eof;
|
||||
|
||||
### Get next line:
|
||||
my $sr = *$self->{SR};
|
||||
my $i = *$self->{Pos}; ### Start matching at this point.
|
||||
|
||||
### Minimal impact implementation!
|
||||
### We do the fast fast thing (no regexps) if using the
|
||||
### classic input record separator.
|
||||
|
||||
### Case 1: $/ is undef: slurp all...
|
||||
if (!defined($/)) {
|
||||
*$self->{Pos} = length $$sr;
|
||||
return substr($$sr, $i);
|
||||
}
|
||||
|
||||
### Case 2: $/ is "\n": zoom zoom zoom...
|
||||
elsif ($/ eq "\012") {
|
||||
|
||||
### Seek ahead for "\n"... yes, this really is faster than regexps.
|
||||
my $len = length($$sr);
|
||||
for (; $i < $len; ++$i) {
|
||||
last if ord (substr ($$sr, $i, 1)) == 10;
|
||||
}
|
||||
|
||||
### Extract the line:
|
||||
my $line;
|
||||
if ($i < $len) { ### We found a "\n":
|
||||
$line = substr ($$sr, *$self->{Pos}, $i - *$self->{Pos} + 1);
|
||||
*$self->{Pos} = $i+1; ### Remember where we finished up.
|
||||
}
|
||||
else { ### No "\n"; slurp the remainder:
|
||||
$line = substr ($$sr, *$self->{Pos}, $i - *$self->{Pos});
|
||||
*$self->{Pos} = $len;
|
||||
}
|
||||
return $line;
|
||||
}
|
||||
|
||||
### Case 3: $/ is ref to int. Do fixed-size records.
|
||||
### (Thanks to Dominique Quatravaux.)
|
||||
elsif (ref($/)) {
|
||||
my $len = length($$sr);
|
||||
my $i = ${$/} + 0;
|
||||
my $line = substr ($$sr, *$self->{Pos}, $i);
|
||||
*$self->{Pos} += $i;
|
||||
*$self->{Pos} = $len if (*$self->{Pos} > $len);
|
||||
return $line;
|
||||
}
|
||||
|
||||
### Case 4: $/ is either "" (paragraphs) or something weird...
|
||||
### This is Graham's general-purpose stuff, which might be
|
||||
### a tad slower than Case 2 for typical data, because
|
||||
### of the regexps.
|
||||
else {
|
||||
pos($$sr) = $i;
|
||||
|
||||
### If in paragraph mode, skip leading lines (and update i!):
|
||||
length($/) or
|
||||
(($$sr =~ m/\G\n*/g) and ($i = pos($$sr)));
|
||||
|
||||
### If we see the separator in the buffer ahead...
|
||||
if (length($/)
|
||||
? $$sr =~ m,\Q$/\E,g ### (ordinary sep) TBD: precomp!
|
||||
: $$sr =~ m,\n\n,g ### (a paragraph)
|
||||
) {
|
||||
*$self->{Pos} = pos $$sr;
|
||||
return substr($$sr, $i, *$self->{Pos}-$i);
|
||||
}
|
||||
### Else if no separator remains, just slurp the rest:
|
||||
else {
|
||||
*$self->{Pos} = length $$sr;
|
||||
return substr($$sr, $i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#------------------------------
|
||||
|
||||
=item getlines
|
||||
|
||||
I<Instance method.>
|
||||
Get all remaining lines.
|
||||
It will croak() if accidentally called in a scalar context.
|
||||
|
||||
=cut
|
||||
|
||||
sub getlines {
|
||||
my $self = shift;
|
||||
wantarray or croak("can't call getlines in scalar context!");
|
||||
my ($line, @lines);
|
||||
push @lines, $line while (defined($line = $self->getline));
|
||||
@lines;
|
||||
}
|
||||
|
||||
#------------------------------
|
||||
|
||||
=item print ARGS...
|
||||
|
||||
I<Instance method.>
|
||||
Print ARGS to the underlying scalar.
|
||||
|
||||
B<Warning:> this continues to always cause a seek to the end
|
||||
of the string, but if you perform seek()s and tell()s, it is
|
||||
still safer to explicitly seek-to-end before subsequent print()s.
|
||||
|
||||
=cut
|
||||
|
||||
sub print {
|
||||
my $self = shift;
|
||||
*$self->{Pos} = length(${*$self->{SR}} .= join('', @_) . (defined($\) ? $\ : ""));
|
||||
1;
|
||||
}
|
||||
sub _unsafe_print {
|
||||
my $self = shift;
|
||||
my $append = join('', @_) . $\;
|
||||
${*$self->{SR}} .= $append;
|
||||
*$self->{Pos} += length($append);
|
||||
1;
|
||||
}
|
||||
sub _old_print {
|
||||
my $self = shift;
|
||||
${*$self->{SR}} .= join('', @_) . $\;
|
||||
*$self->{Pos} = length(${*$self->{SR}});
|
||||
1;
|
||||
}
|
||||
|
||||
|
||||
#------------------------------
|
||||
|
||||
=item read BUF, NBYTES, [OFFSET]
|
||||
|
||||
I<Instance method.>
|
||||
Read some bytes from the scalar.
|
||||
Returns the number of bytes actually read, 0 on end-of-file, undef on error.
|
||||
|
||||
=cut
|
||||
|
||||
sub read {
|
||||
my $self = $_[0];
|
||||
my $n = $_[2];
|
||||
my $off = $_[3] || 0;
|
||||
|
||||
my $read = substr(${*$self->{SR}}, *$self->{Pos}, $n);
|
||||
$n = length($read);
|
||||
*$self->{Pos} += $n;
|
||||
($off ? substr($_[1], $off) : $_[1]) = $read;
|
||||
return $n;
|
||||
}
|
||||
|
||||
#------------------------------
|
||||
|
||||
=item write BUF, NBYTES, [OFFSET]
|
||||
|
||||
I<Instance method.>
|
||||
Write some bytes to the scalar.
|
||||
|
||||
=cut
|
||||
|
||||
sub write {
|
||||
my $self = $_[0];
|
||||
my $n = $_[2];
|
||||
my $off = $_[3] || 0;
|
||||
|
||||
my $data = substr($_[1], $off, $n);
|
||||
$n = length($data);
|
||||
$self->print($data);
|
||||
return $n;
|
||||
}
|
||||
|
||||
#------------------------------
|
||||
|
||||
=item sysread BUF, LEN, [OFFSET]
|
||||
|
||||
I<Instance method.>
|
||||
Read some bytes from the scalar.
|
||||
Returns the number of bytes actually read, 0 on end-of-file, undef on error.
|
||||
|
||||
=cut
|
||||
|
||||
sub sysread {
|
||||
my $self = shift;
|
||||
$self->read(@_);
|
||||
}
|
||||
|
||||
#------------------------------
|
||||
|
||||
=item syswrite BUF, NBYTES, [OFFSET]
|
||||
|
||||
I<Instance method.>
|
||||
Write some bytes to the scalar.
|
||||
|
||||
=cut
|
||||
|
||||
sub syswrite {
|
||||
my $self = shift;
|
||||
$self->write(@_);
|
||||
}
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
#==============================
|
||||
|
||||
=head2 Seeking/telling and other attributes
|
||||
|
||||
=over 4
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
#------------------------------
|
||||
|
||||
=item autoflush
|
||||
|
||||
I<Instance method.>
|
||||
No-op, provided for OO compatibility.
|
||||
|
||||
=cut
|
||||
|
||||
sub autoflush {}
|
||||
|
||||
#------------------------------
|
||||
|
||||
=item binmode
|
||||
|
||||
I<Instance method.>
|
||||
No-op, provided for OO compatibility.
|
||||
|
||||
=cut
|
||||
|
||||
sub binmode {}
|
||||
|
||||
#------------------------------
|
||||
|
||||
=item clearerr
|
||||
|
||||
I<Instance method.> Clear the error and EOF flags. A no-op.
|
||||
|
||||
=cut
|
||||
|
||||
sub clearerr { 1 }
|
||||
|
||||
#------------------------------
|
||||
|
||||
=item eof
|
||||
|
||||
I<Instance method.> Are we at end of file?
|
||||
|
||||
=cut
|
||||
|
||||
sub eof {
|
||||
my $self = shift;
|
||||
(*$self->{Pos} >= length(${*$self->{SR}}));
|
||||
}
|
||||
|
||||
#------------------------------
|
||||
|
||||
=item seek OFFSET, WHENCE
|
||||
|
||||
I<Instance method.> Seek to a given position in the stream.
|
||||
|
||||
=cut
|
||||
|
||||
sub seek {
|
||||
my ($self, $pos, $whence) = @_;
|
||||
my $eofpos = length(${*$self->{SR}});
|
||||
|
||||
### Seek:
|
||||
if ($whence == 0) { *$self->{Pos} = $pos } ### SEEK_SET
|
||||
elsif ($whence == 1) { *$self->{Pos} += $pos } ### SEEK_CUR
|
||||
elsif ($whence == 2) { *$self->{Pos} = $eofpos + $pos} ### SEEK_END
|
||||
else { croak "bad seek whence ($whence)" }
|
||||
|
||||
### Fixup:
|
||||
if (*$self->{Pos} < 0) { *$self->{Pos} = 0 }
|
||||
if (*$self->{Pos} > $eofpos) { *$self->{Pos} = $eofpos }
|
||||
return 1;
|
||||
}
|
||||
|
||||
#------------------------------
|
||||
|
||||
=item sysseek OFFSET, WHENCE
|
||||
|
||||
I<Instance method.> Identical to C<seek OFFSET, WHENCE>, I<q.v.>
|
||||
|
||||
=cut
|
||||
|
||||
sub sysseek {
|
||||
my $self = shift;
|
||||
$self->seek (@_);
|
||||
}
|
||||
|
||||
#------------------------------
|
||||
|
||||
=item tell
|
||||
|
||||
I<Instance method.>
|
||||
Return the current position in the stream, as a numeric offset.
|
||||
|
||||
=cut
|
||||
|
||||
sub tell { *{shift()}->{Pos} }
|
||||
|
||||
#------------------------------
|
||||
|
||||
=item use_RS [YESNO]
|
||||
|
||||
I<Instance method.>
|
||||
B<Deprecated and ignored.>
|
||||
Obey the current setting of $/, like IO::Handle does?
|
||||
Default is false in 1.x, but cold-welded true in 2.x and later.
|
||||
|
||||
=cut
|
||||
|
||||
sub use_RS {
|
||||
my ($self, $yesno) = @_;
|
||||
carp "use_RS is deprecated and ignored; \$/ is always consulted\n";
|
||||
}
|
||||
|
||||
#------------------------------
|
||||
|
||||
=item setpos POS
|
||||
|
||||
I<Instance method.>
|
||||
Set the current position, using the opaque value returned by C<getpos()>.
|
||||
|
||||
=cut
|
||||
|
||||
sub setpos { shift->seek($_[0],0) }
|
||||
|
||||
#------------------------------
|
||||
|
||||
=item getpos
|
||||
|
||||
I<Instance method.>
|
||||
Return the current position in the string, as an opaque object.
|
||||
|
||||
=cut
|
||||
|
||||
*getpos = \&tell;
|
||||
|
||||
|
||||
#------------------------------
|
||||
|
||||
=item sref
|
||||
|
||||
I<Instance method.>
|
||||
Return a reference to the underlying scalar.
|
||||
|
||||
=cut
|
||||
|
||||
sub sref { *{shift()}->{SR} }
|
||||
|
||||
|
||||
#------------------------------
|
||||
# Tied handle methods...
|
||||
#------------------------------
|
||||
|
||||
# Conventional tiehandle interface:
|
||||
sub TIEHANDLE {
|
||||
((defined($_[1]) && UNIVERSAL::isa($_[1], __PACKAGE__))
|
||||
? $_[1]
|
||||
: shift->new(@_));
|
||||
}
|
||||
sub GETC { shift->getc(@_) }
|
||||
sub PRINT { shift->print(@_) }
|
||||
sub PRINTF { shift->print(sprintf(shift, @_)) }
|
||||
sub READ { shift->read(@_) }
|
||||
sub READLINE { wantarray ? shift->getlines(@_) : shift->getline(@_) }
|
||||
sub WRITE { shift->write(@_); }
|
||||
sub CLOSE { shift->close(@_); }
|
||||
sub SEEK { shift->seek(@_); }
|
||||
sub TELL { shift->tell(@_); }
|
||||
sub EOF { shift->eof(@_); }
|
||||
sub FILENO { -1 }
|
||||
|
||||
#------------------------------------------------------------
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
=head1 WARNINGS
|
||||
|
||||
Perl's TIEHANDLE spec was incomplete prior to 5.005_57;
|
||||
it was missing support for C<seek()>, C<tell()>, and C<eof()>.
|
||||
Attempting to use these functions with an IO::Scalar will not work
|
||||
prior to 5.005_57. IO::Scalar will not have the relevant methods
|
||||
invoked; and even worse, this kind of bug can lie dormant for a while.
|
||||
If you turn warnings on (via C<$^W> or C<perl -w>),
|
||||
and you see something like this...
|
||||
|
||||
attempt to seek on unopened filehandle
|
||||
|
||||
...then you are probably trying to use one of these functions
|
||||
on an IO::Scalar with an old Perl. The remedy is to simply
|
||||
use the OO version; e.g.:
|
||||
|
||||
$SH->seek(0,0); ### GOOD: will work on any 5.005
|
||||
seek($SH,0,0); ### WARNING: will only work on 5.005_57 and beyond
|
||||
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
$Id: Scalar.pm,v 1.6 2005/02/10 21:21:53 dfs Exp $
|
||||
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
=head2 Primary Maintainer
|
||||
|
||||
David F. Skoll (F<dfs@roaringpenguin.com>).
|
||||
|
||||
=head2 Principal author
|
||||
|
||||
Eryq (F<eryq@zeegee.com>).
|
||||
President, ZeeGee Software Inc (F<http://www.zeegee.com>).
|
||||
|
||||
|
||||
=head2 Other contributors
|
||||
|
||||
The full set of contributors always includes the folks mentioned
|
||||
in L<IO::Stringy/"CHANGE LOG">. But just the same, special
|
||||
thanks to the following individuals for their invaluable contributions
|
||||
(if I've forgotten or misspelled your name, please email me!):
|
||||
|
||||
I<Andy Glew,>
|
||||
for contributing C<getc()>.
|
||||
|
||||
I<Brandon Browning,>
|
||||
for suggesting C<opened()>.
|
||||
|
||||
I<David Richter,>
|
||||
for finding and fixing the bug in C<PRINTF()>.
|
||||
|
||||
I<Eric L. Brine,>
|
||||
for his offset-using read() and write() implementations.
|
||||
|
||||
I<Richard Jones,>
|
||||
for his patches to massively improve the performance of C<getline()>
|
||||
and add C<sysread> and C<syswrite>.
|
||||
|
||||
I<B. K. Oxley (binkley),>
|
||||
for stringification and inheritance improvements,
|
||||
and sundry good ideas.
|
||||
|
||||
I<Doug Wilson,>
|
||||
for the IO::Handle inheritance and automatic tie-ing.
|
||||
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<IO::String>, which is quite similar but which was designed
|
||||
more-recently and with an IO::Handle-like interface in mind,
|
||||
so you could mix OO- and native-filehandle usage without using tied().
|
||||
|
||||
I<Note:> as of version 2.x, these classes all work like
|
||||
their IO::Handle counterparts, so we have comparable
|
||||
functionality to IO::String.
|
||||
|
||||
=cut
|
||||
|
||||
182
database/perl/lib/Test/Builder/Module.pm
Normal file
182
database/perl/lib/Test/Builder/Module.pm
Normal file
@@ -0,0 +1,182 @@
|
||||
package Test::Builder::Module;
|
||||
|
||||
use strict;
|
||||
|
||||
use Test::Builder;
|
||||
|
||||
require Exporter;
|
||||
our @ISA = qw(Exporter);
|
||||
|
||||
our $VERSION = '1.302183';
|
||||
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Test::Builder::Module - Base class for test modules
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
# Emulates Test::Simple
|
||||
package Your::Module;
|
||||
|
||||
my $CLASS = __PACKAGE__;
|
||||
|
||||
use parent 'Test::Builder::Module';
|
||||
@EXPORT = qw(ok);
|
||||
|
||||
sub ok ($;$) {
|
||||
my $tb = $CLASS->builder;
|
||||
return $tb->ok(@_);
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This is a superclass for L<Test::Builder>-based modules. It provides a
|
||||
handful of common functionality and a method of getting at the underlying
|
||||
L<Test::Builder> object.
|
||||
|
||||
|
||||
=head2 Importing
|
||||
|
||||
Test::Builder::Module is a subclass of L<Exporter> which means your
|
||||
module is also a subclass of Exporter. @EXPORT, @EXPORT_OK, etc...
|
||||
all act normally.
|
||||
|
||||
A few methods are provided to do the C<< use Your::Module tests => 23 >> part
|
||||
for you.
|
||||
|
||||
=head3 import
|
||||
|
||||
Test::Builder::Module provides an C<import()> method which acts in the
|
||||
same basic way as L<Test::More>'s, setting the plan and controlling
|
||||
exporting of functions and variables. This allows your module to set
|
||||
the plan independent of L<Test::More>.
|
||||
|
||||
All arguments passed to C<import()> are passed onto
|
||||
C<< Your::Module->builder->plan() >> with the exception of
|
||||
C<< import =>[qw(things to import)] >>.
|
||||
|
||||
use Your::Module import => [qw(this that)], tests => 23;
|
||||
|
||||
says to import the functions C<this()> and C<that()> as well as set the plan
|
||||
to be 23 tests.
|
||||
|
||||
C<import()> also sets the C<exported_to()> attribute of your builder to be
|
||||
the caller of the C<import()> function.
|
||||
|
||||
Additional behaviors can be added to your C<import()> method by overriding
|
||||
C<import_extra()>.
|
||||
|
||||
=cut
|
||||
|
||||
sub import {
|
||||
my($class) = shift;
|
||||
|
||||
Test2::API::test2_load() unless Test2::API::test2_in_preload();
|
||||
|
||||
# Don't run all this when loading ourself.
|
||||
return 1 if $class eq 'Test::Builder::Module';
|
||||
|
||||
my $test = $class->builder;
|
||||
|
||||
my $caller = caller;
|
||||
|
||||
$test->exported_to($caller);
|
||||
|
||||
$class->import_extra( \@_ );
|
||||
my(@imports) = $class->_strip_imports( \@_ );
|
||||
|
||||
$test->plan(@_);
|
||||
|
||||
local $Exporter::ExportLevel = $Exporter::ExportLevel + 1;
|
||||
$class->Exporter::import(@imports);
|
||||
}
|
||||
|
||||
sub _strip_imports {
|
||||
my $class = shift;
|
||||
my $list = shift;
|
||||
|
||||
my @imports = ();
|
||||
my @other = ();
|
||||
my $idx = 0;
|
||||
while( $idx <= $#{$list} ) {
|
||||
my $item = $list->[$idx];
|
||||
|
||||
if( defined $item and $item eq 'import' ) {
|
||||
push @imports, @{ $list->[ $idx + 1 ] };
|
||||
$idx++;
|
||||
}
|
||||
else {
|
||||
push @other, $item;
|
||||
}
|
||||
|
||||
$idx++;
|
||||
}
|
||||
|
||||
@$list = @other;
|
||||
|
||||
return @imports;
|
||||
}
|
||||
|
||||
=head3 import_extra
|
||||
|
||||
Your::Module->import_extra(\@import_args);
|
||||
|
||||
C<import_extra()> is called by C<import()>. It provides an opportunity for you
|
||||
to add behaviors to your module based on its import list.
|
||||
|
||||
Any extra arguments which shouldn't be passed on to C<plan()> should be
|
||||
stripped off by this method.
|
||||
|
||||
See L<Test::More> for an example of its use.
|
||||
|
||||
B<NOTE> This mechanism is I<VERY ALPHA AND LIKELY TO CHANGE> as it
|
||||
feels like a bit of an ugly hack in its current form.
|
||||
|
||||
=cut
|
||||
|
||||
sub import_extra { }
|
||||
|
||||
=head2 Builder
|
||||
|
||||
Test::Builder::Module provides some methods of getting at the underlying
|
||||
Test::Builder object.
|
||||
|
||||
=head3 builder
|
||||
|
||||
my $builder = Your::Class->builder;
|
||||
|
||||
This method returns the L<Test::Builder> object associated with Your::Class.
|
||||
It is not a constructor so you can call it as often as you like.
|
||||
|
||||
This is the preferred way to get the L<Test::Builder> object. You should
|
||||
I<not> get it via C<< Test::Builder->new >> as was previously
|
||||
recommended.
|
||||
|
||||
The object returned by C<builder()> may change at runtime so you should
|
||||
call C<builder()> inside each function rather than store it in a global.
|
||||
|
||||
sub ok {
|
||||
my $builder = Your::Class->builder;
|
||||
|
||||
return $builder->ok(@_);
|
||||
}
|
||||
|
||||
|
||||
=cut
|
||||
|
||||
sub builder {
|
||||
return Test::Builder->new;
|
||||
}
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<< Test2::Manual::Tooling::TestBuilder >> describes the improved
|
||||
options for writing testing modules provided by L<< Test2 >>.
|
||||
|
||||
=cut
|
||||
|
||||
1;
|
||||
675
database/perl/lib/Test/Builder/Tester.pm
Normal file
675
database/perl/lib/Test/Builder/Tester.pm
Normal file
@@ -0,0 +1,675 @@
|
||||
package Test::Builder::Tester;
|
||||
|
||||
use strict;
|
||||
our $VERSION = '1.302183';
|
||||
|
||||
use Test::Builder;
|
||||
use Symbol;
|
||||
use Carp;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Test::Builder::Tester - test testsuites that have been built with
|
||||
Test::Builder
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use Test::Builder::Tester tests => 1;
|
||||
use Test::More;
|
||||
|
||||
test_out("not ok 1 - foo");
|
||||
test_fail(+1);
|
||||
fail("foo");
|
||||
test_test("fail works");
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
A module that helps you test testing modules that are built with
|
||||
L<Test::Builder>.
|
||||
|
||||
The testing system is designed to be used by performing a three step
|
||||
process for each test you wish to test. This process starts with using
|
||||
C<test_out> and C<test_err> in advance to declare what the testsuite you
|
||||
are testing will output with L<Test::Builder> to stdout and stderr.
|
||||
|
||||
You then can run the test(s) from your test suite that call
|
||||
L<Test::Builder>. At this point the output of L<Test::Builder> is
|
||||
safely captured by L<Test::Builder::Tester> rather than being
|
||||
interpreted as real test output.
|
||||
|
||||
The final stage is to call C<test_test> that will simply compare what you
|
||||
predeclared to what L<Test::Builder> actually outputted, and report the
|
||||
results back with a "ok" or "not ok" (with debugging) to the normal
|
||||
output.
|
||||
|
||||
=cut
|
||||
|
||||
####
|
||||
# set up testing
|
||||
####
|
||||
|
||||
my $t = Test::Builder->new;
|
||||
|
||||
###
|
||||
# make us an exporter
|
||||
###
|
||||
|
||||
use Exporter;
|
||||
our @ISA = qw(Exporter);
|
||||
|
||||
our @EXPORT = qw(test_out test_err test_fail test_diag test_test line_num);
|
||||
|
||||
sub import {
|
||||
my $class = shift;
|
||||
my(@plan) = @_;
|
||||
|
||||
my $caller = caller;
|
||||
|
||||
$t->exported_to($caller);
|
||||
$t->plan(@plan);
|
||||
|
||||
my @imports = ();
|
||||
foreach my $idx ( 0 .. $#plan ) {
|
||||
if( $plan[$idx] eq 'import' ) {
|
||||
@imports = @{ $plan[ $idx + 1 ] };
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
__PACKAGE__->export_to_level( 1, __PACKAGE__, @imports );
|
||||
}
|
||||
|
||||
###
|
||||
# set up file handles
|
||||
###
|
||||
|
||||
# create some private file handles
|
||||
my $output_handle = gensym;
|
||||
my $error_handle = gensym;
|
||||
|
||||
# and tie them to this package
|
||||
my $out = tie *$output_handle, "Test::Builder::Tester::Tie", "STDOUT";
|
||||
my $err = tie *$error_handle, "Test::Builder::Tester::Tie", "STDERR";
|
||||
|
||||
####
|
||||
# exported functions
|
||||
####
|
||||
|
||||
# for remembering that we're testing and where we're testing at
|
||||
my $testing = 0;
|
||||
my $testing_num;
|
||||
my $original_is_passing;
|
||||
|
||||
# remembering where the file handles were originally connected
|
||||
my $original_output_handle;
|
||||
my $original_failure_handle;
|
||||
my $original_todo_handle;
|
||||
my $original_formatter;
|
||||
|
||||
my $original_harness_env;
|
||||
|
||||
# function that starts testing and redirects the filehandles for now
|
||||
sub _start_testing {
|
||||
# Hack for things that conditioned on Test-Stream being loaded
|
||||
$INC{'Test/Stream.pm'} ||= 'fake' if $INC{'Test/Moose/More.pm'};
|
||||
# even if we're running under Test::Harness pretend we're not
|
||||
# for now. This needed so Test::Builder doesn't add extra spaces
|
||||
$original_harness_env = $ENV{HARNESS_ACTIVE} || 0;
|
||||
$ENV{HARNESS_ACTIVE} = 0;
|
||||
|
||||
my $hub = $t->{Hub} || ($t->{Stack} ? $t->{Stack}->top : Test2::API::test2_stack->top);
|
||||
$original_formatter = $hub->format;
|
||||
unless ($original_formatter && $original_formatter->isa('Test::Builder::Formatter')) {
|
||||
my $fmt = Test::Builder::Formatter->new;
|
||||
$hub->format($fmt);
|
||||
}
|
||||
|
||||
# remember what the handles were set to
|
||||
$original_output_handle = $t->output();
|
||||
$original_failure_handle = $t->failure_output();
|
||||
$original_todo_handle = $t->todo_output();
|
||||
|
||||
# switch out to our own handles
|
||||
$t->output($output_handle);
|
||||
$t->failure_output($error_handle);
|
||||
$t->todo_output($output_handle);
|
||||
|
||||
# clear the expected list
|
||||
$out->reset();
|
||||
$err->reset();
|
||||
|
||||
# remember that we're testing
|
||||
$testing = 1;
|
||||
$testing_num = $t->current_test;
|
||||
$t->current_test(0);
|
||||
$original_is_passing = $t->is_passing;
|
||||
$t->is_passing(1);
|
||||
|
||||
# look, we shouldn't do the ending stuff
|
||||
$t->no_ending(1);
|
||||
}
|
||||
|
||||
=head2 Functions
|
||||
|
||||
These are the six methods that are exported as default.
|
||||
|
||||
=over 4
|
||||
|
||||
=item test_out
|
||||
|
||||
=item test_err
|
||||
|
||||
Procedures for predeclaring the output that your test suite is
|
||||
expected to produce until C<test_test> is called. These procedures
|
||||
automatically assume that each line terminates with "\n". So
|
||||
|
||||
test_out("ok 1","ok 2");
|
||||
|
||||
is the same as
|
||||
|
||||
test_out("ok 1\nok 2");
|
||||
|
||||
which is even the same as
|
||||
|
||||
test_out("ok 1");
|
||||
test_out("ok 2");
|
||||
|
||||
Once C<test_out> or C<test_err> (or C<test_fail> or C<test_diag>) have
|
||||
been called, all further output from L<Test::Builder> will be
|
||||
captured by L<Test::Builder::Tester>. This means that you will not
|
||||
be able perform further tests to the normal output in the normal way
|
||||
until you call C<test_test> (well, unless you manually meddle with the
|
||||
output filehandles)
|
||||
|
||||
=cut
|
||||
|
||||
sub test_out {
|
||||
# do we need to do any setup?
|
||||
_start_testing() unless $testing;
|
||||
|
||||
$out->expect(@_);
|
||||
}
|
||||
|
||||
sub test_err {
|
||||
# do we need to do any setup?
|
||||
_start_testing() unless $testing;
|
||||
|
||||
$err->expect(@_);
|
||||
}
|
||||
|
||||
=item test_fail
|
||||
|
||||
Because the standard failure message that L<Test::Builder> produces
|
||||
whenever a test fails will be a common occurrence in your test error
|
||||
output, and because it has changed between Test::Builder versions, rather
|
||||
than forcing you to call C<test_err> with the string all the time like
|
||||
so
|
||||
|
||||
test_err("# Failed test ($0 at line ".line_num(+1).")");
|
||||
|
||||
C<test_fail> exists as a convenience function that can be called
|
||||
instead. It takes one argument, the offset from the current line that
|
||||
the line that causes the fail is on.
|
||||
|
||||
test_fail(+1);
|
||||
|
||||
This means that the example in the synopsis could be rewritten
|
||||
more simply as:
|
||||
|
||||
test_out("not ok 1 - foo");
|
||||
test_fail(+1);
|
||||
fail("foo");
|
||||
test_test("fail works");
|
||||
|
||||
=cut
|
||||
|
||||
sub test_fail {
|
||||
# do we need to do any setup?
|
||||
_start_testing() unless $testing;
|
||||
|
||||
# work out what line we should be on
|
||||
my( $package, $filename, $line ) = caller;
|
||||
$line = $line + ( shift() || 0 ); # prevent warnings
|
||||
|
||||
# expect that on stderr
|
||||
$err->expect("# Failed test ($filename at line $line)");
|
||||
}
|
||||
|
||||
=item test_diag
|
||||
|
||||
As most of the remaining expected output to the error stream will be
|
||||
created by L<Test::Builder>'s C<diag> function, L<Test::Builder::Tester>
|
||||
provides a convenience function C<test_diag> that you can use instead of
|
||||
C<test_err>.
|
||||
|
||||
The C<test_diag> function prepends comment hashes and spacing to the
|
||||
start and newlines to the end of the expected output passed to it and
|
||||
adds it to the list of expected error output. So, instead of writing
|
||||
|
||||
test_err("# Couldn't open file");
|
||||
|
||||
you can write
|
||||
|
||||
test_diag("Couldn't open file");
|
||||
|
||||
Remember that L<Test::Builder>'s diag function will not add newlines to
|
||||
the end of output and test_diag will. So to check
|
||||
|
||||
Test::Builder->new->diag("foo\n","bar\n");
|
||||
|
||||
You would do
|
||||
|
||||
test_diag("foo","bar")
|
||||
|
||||
without the newlines.
|
||||
|
||||
=cut
|
||||
|
||||
sub test_diag {
|
||||
# do we need to do any setup?
|
||||
_start_testing() unless $testing;
|
||||
|
||||
# expect the same thing, but prepended with "# "
|
||||
local $_;
|
||||
$err->expect( map { "# $_" } @_ );
|
||||
}
|
||||
|
||||
=item test_test
|
||||
|
||||
Actually performs the output check testing the tests, comparing the
|
||||
data (with C<eq>) that we have captured from L<Test::Builder> against
|
||||
what was declared with C<test_out> and C<test_err>.
|
||||
|
||||
This takes name/value pairs that effect how the test is run.
|
||||
|
||||
=over
|
||||
|
||||
=item title (synonym 'name', 'label')
|
||||
|
||||
The name of the test that will be displayed after the C<ok> or C<not
|
||||
ok>.
|
||||
|
||||
=item skip_out
|
||||
|
||||
Setting this to a true value will cause the test to ignore if the
|
||||
output sent by the test to the output stream does not match that
|
||||
declared with C<test_out>.
|
||||
|
||||
=item skip_err
|
||||
|
||||
Setting this to a true value will cause the test to ignore if the
|
||||
output sent by the test to the error stream does not match that
|
||||
declared with C<test_err>.
|
||||
|
||||
=back
|
||||
|
||||
As a convenience, if only one argument is passed then this argument
|
||||
is assumed to be the name of the test (as in the above examples.)
|
||||
|
||||
Once C<test_test> has been run test output will be redirected back to
|
||||
the original filehandles that L<Test::Builder> was connected to
|
||||
(probably STDOUT and STDERR,) meaning any further tests you run
|
||||
will function normally and cause success/errors for L<Test::Harness>.
|
||||
|
||||
=cut
|
||||
|
||||
sub test_test {
|
||||
# END the hack
|
||||
delete $INC{'Test/Stream.pm'} if $INC{'Test/Stream.pm'} && $INC{'Test/Stream.pm'} eq 'fake';
|
||||
# decode the arguments as described in the pod
|
||||
my $mess;
|
||||
my %args;
|
||||
if( @_ == 1 ) {
|
||||
$mess = shift
|
||||
}
|
||||
else {
|
||||
%args = @_;
|
||||
$mess = $args{name} if exists( $args{name} );
|
||||
$mess = $args{title} if exists( $args{title} );
|
||||
$mess = $args{label} if exists( $args{label} );
|
||||
}
|
||||
|
||||
# er, are we testing?
|
||||
croak "Not testing. You must declare output with a test function first."
|
||||
unless $testing;
|
||||
|
||||
|
||||
my $hub = $t->{Hub} || Test2::API::test2_stack->top;
|
||||
$hub->format($original_formatter);
|
||||
|
||||
# okay, reconnect the test suite back to the saved handles
|
||||
$t->output($original_output_handle);
|
||||
$t->failure_output($original_failure_handle);
|
||||
$t->todo_output($original_todo_handle);
|
||||
|
||||
# restore the test no, etc, back to the original point
|
||||
$t->current_test($testing_num);
|
||||
$testing = 0;
|
||||
$t->is_passing($original_is_passing);
|
||||
|
||||
# re-enable the original setting of the harness
|
||||
$ENV{HARNESS_ACTIVE} = $original_harness_env;
|
||||
|
||||
# check the output we've stashed
|
||||
unless( $t->ok( ( $args{skip_out} || $out->check ) &&
|
||||
( $args{skip_err} || $err->check ), $mess )
|
||||
)
|
||||
{
|
||||
# print out the diagnostic information about why this
|
||||
# test failed
|
||||
|
||||
local $_;
|
||||
|
||||
$t->diag( map { "$_\n" } $out->complaint )
|
||||
unless $args{skip_out} || $out->check;
|
||||
|
||||
$t->diag( map { "$_\n" } $err->complaint )
|
||||
unless $args{skip_err} || $err->check;
|
||||
}
|
||||
}
|
||||
|
||||
=item line_num
|
||||
|
||||
A utility function that returns the line number that the function was
|
||||
called on. You can pass it an offset which will be added to the
|
||||
result. This is very useful for working out the correct text of
|
||||
diagnostic functions that contain line numbers.
|
||||
|
||||
Essentially this is the same as the C<__LINE__> macro, but the
|
||||
C<line_num(+3)> idiom is arguably nicer.
|
||||
|
||||
=cut
|
||||
|
||||
sub line_num {
|
||||
my( $package, $filename, $line ) = caller;
|
||||
return $line + ( shift() || 0 ); # prevent warnings
|
||||
}
|
||||
|
||||
=back
|
||||
|
||||
In addition to the six exported functions there exists one
|
||||
function that can only be accessed with a fully qualified function
|
||||
call.
|
||||
|
||||
=over 4
|
||||
|
||||
=item color
|
||||
|
||||
When C<test_test> is called and the output that your tests generate
|
||||
does not match that which you declared, C<test_test> will print out
|
||||
debug information showing the two conflicting versions. As this
|
||||
output itself is debug information it can be confusing which part of
|
||||
the output is from C<test_test> and which was the original output from
|
||||
your original tests. Also, it may be hard to spot things like
|
||||
extraneous whitespace at the end of lines that may cause your test to
|
||||
fail even though the output looks similar.
|
||||
|
||||
To assist you C<test_test> can colour the background of the debug
|
||||
information to disambiguate the different types of output. The debug
|
||||
output will have its background coloured green and red. The green
|
||||
part represents the text which is the same between the executed and
|
||||
actual output, the red shows which part differs.
|
||||
|
||||
The C<color> function determines if colouring should occur or not.
|
||||
Passing it a true or false value will enable or disable colouring
|
||||
respectively, and the function called with no argument will return the
|
||||
current setting.
|
||||
|
||||
To enable colouring from the command line, you can use the
|
||||
L<Text::Builder::Tester::Color> module like so:
|
||||
|
||||
perl -Mlib=Text::Builder::Tester::Color test.t
|
||||
|
||||
Or by including the L<Test::Builder::Tester::Color> module directly in
|
||||
the PERL5LIB.
|
||||
|
||||
=cut
|
||||
|
||||
my $color;
|
||||
|
||||
sub color {
|
||||
$color = shift if @_;
|
||||
$color;
|
||||
}
|
||||
|
||||
=back
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
Test::Builder::Tester does not handle plans well. It has never done anything
|
||||
special with plans. This means that plans from outside Test::Builder::Tester
|
||||
will effect Test::Builder::Tester, worse plans when using Test::Builder::Tester
|
||||
will effect overall testing. At this point there are no plans to fix this bug
|
||||
as people have come to depend on it, and Test::Builder::Tester is now
|
||||
discouraged in favor of C<Test2::API::intercept()>. See
|
||||
L<https://github.com/Test-More/test-more/issues/667>
|
||||
|
||||
Calls C<< Test::Builder->no_ending >> turning off the ending tests.
|
||||
This is needed as otherwise it will trip out because we've run more
|
||||
tests than we strictly should have and it'll register any failures we
|
||||
had that we were testing for as real failures.
|
||||
|
||||
The color function doesn't work unless L<Term::ANSIColor> is
|
||||
compatible with your terminal. Additionally, L<Win32::Console::ANSI>
|
||||
must be installed on windows platforms for color output.
|
||||
|
||||
Bugs (and requests for new features) can be reported to the author
|
||||
though GitHub:
|
||||
L<https://github.com/Test-More/test-more/issues>
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Copyright Mark Fowler E<lt>mark@twoshortplanks.comE<gt> 2002, 2004.
|
||||
|
||||
Some code taken from L<Test::More> and L<Test::Catch>, written by
|
||||
Michael G Schwern E<lt>schwern@pobox.comE<gt>. Hence, those parts
|
||||
Copyright Micheal G Schwern 2001. Used and distributed with
|
||||
permission.
|
||||
|
||||
This program is free software; you can redistribute it
|
||||
and/or modify it under the same terms as Perl itself.
|
||||
|
||||
=head1 MAINTAINERS
|
||||
|
||||
=over 4
|
||||
|
||||
=item Chad Granum E<lt>exodist@cpan.orgE<gt>
|
||||
|
||||
=back
|
||||
|
||||
=head1 NOTES
|
||||
|
||||
Thanks to Richard Clamp E<lt>richardc@unixbeard.netE<gt> for letting
|
||||
me use his testing system to try this module out on.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<Test::Builder>, L<Test::Builder::Tester::Color>, L<Test::More>.
|
||||
|
||||
=cut
|
||||
|
||||
1;
|
||||
|
||||
####################################################################
|
||||
# Helper class that is used to remember expected and received data
|
||||
|
||||
package Test::Builder::Tester::Tie;
|
||||
|
||||
##
|
||||
# add line(s) to be expected
|
||||
|
||||
sub expect {
|
||||
my $self = shift;
|
||||
|
||||
my @checks = @_;
|
||||
foreach my $check (@checks) {
|
||||
$check = $self->_account_for_subtest($check);
|
||||
$check = $self->_translate_Failed_check($check);
|
||||
push @{ $self->{wanted} }, ref $check ? $check : "$check\n";
|
||||
}
|
||||
}
|
||||
|
||||
sub _account_for_subtest {
|
||||
my( $self, $check ) = @_;
|
||||
|
||||
my $hub = $t->{Stack}->top;
|
||||
my $nesting = $hub->isa('Test2::Hub::Subtest') ? $hub->nested : 0;
|
||||
return ref($check) ? $check : (' ' x $nesting) . $check;
|
||||
}
|
||||
|
||||
sub _translate_Failed_check {
|
||||
my( $self, $check ) = @_;
|
||||
|
||||
if( $check =~ /\A(.*)# (Failed .*test) \((.*?) at line (\d+)\)\Z(?!\n)/ ) {
|
||||
$check = "/\Q$1\E#\\s+\Q$2\E.*?\\n?.*?\Qat $3\E line \Q$4\E.*\\n?/";
|
||||
}
|
||||
|
||||
return $check;
|
||||
}
|
||||
|
||||
##
|
||||
# return true iff the expected data matches the got data
|
||||
|
||||
sub check {
|
||||
my $self = shift;
|
||||
|
||||
# turn off warnings as these might be undef
|
||||
local $^W = 0;
|
||||
|
||||
my @checks = @{ $self->{wanted} };
|
||||
my $got = $self->{got};
|
||||
foreach my $check (@checks) {
|
||||
$check = "\Q$check\E" unless( $check =~ s,^/(.*)/$,$1, or ref $check );
|
||||
return 0 unless $got =~ s/^$check//;
|
||||
}
|
||||
|
||||
return length $got == 0;
|
||||
}
|
||||
|
||||
##
|
||||
# a complaint message about the inputs not matching (to be
|
||||
# used for debugging messages)
|
||||
|
||||
sub complaint {
|
||||
my $self = shift;
|
||||
my $type = $self->type;
|
||||
my $got = $self->got;
|
||||
my $wanted = join '', @{ $self->wanted };
|
||||
|
||||
# are we running in colour mode?
|
||||
if(Test::Builder::Tester::color) {
|
||||
# get color
|
||||
eval { require Term::ANSIColor };
|
||||
unless($@) {
|
||||
eval { require Win32::Console::ANSI } if 'MSWin32' eq $^O; # support color on windows platforms
|
||||
|
||||
# colours
|
||||
|
||||
my $green = Term::ANSIColor::color("black") . Term::ANSIColor::color("on_green");
|
||||
my $red = Term::ANSIColor::color("black") . Term::ANSIColor::color("on_red");
|
||||
my $reset = Term::ANSIColor::color("reset");
|
||||
|
||||
# work out where the two strings start to differ
|
||||
my $char = 0;
|
||||
$char++ while substr( $got, $char, 1 ) eq substr( $wanted, $char, 1 );
|
||||
|
||||
# get the start string and the two end strings
|
||||
my $start = $green . substr( $wanted, 0, $char );
|
||||
my $gotend = $red . substr( $got, $char ) . $reset;
|
||||
my $wantedend = $red . substr( $wanted, $char ) . $reset;
|
||||
|
||||
# make the start turn green on and off
|
||||
$start =~ s/\n/$reset\n$green/g;
|
||||
|
||||
# make the ends turn red on and off
|
||||
$gotend =~ s/\n/$reset\n$red/g;
|
||||
$wantedend =~ s/\n/$reset\n$red/g;
|
||||
|
||||
# rebuild the strings
|
||||
$got = $start . $gotend;
|
||||
$wanted = $start . $wantedend;
|
||||
}
|
||||
}
|
||||
|
||||
my @got = split "\n", $got;
|
||||
my @wanted = split "\n", $wanted;
|
||||
|
||||
$got = "";
|
||||
$wanted = "";
|
||||
|
||||
while (@got || @wanted) {
|
||||
my $g = shift @got || "";
|
||||
my $w = shift @wanted || "";
|
||||
if ($g ne $w) {
|
||||
if($g =~ s/(\s+)$/ |> /g) {
|
||||
$g .= ($_ eq ' ' ? '_' : '\t') for split '', $1;
|
||||
}
|
||||
if($w =~ s/(\s+)$/ |> /g) {
|
||||
$w .= ($_ eq ' ' ? '_' : '\t') for split '', $1;
|
||||
}
|
||||
$g = "> $g";
|
||||
$w = "> $w";
|
||||
}
|
||||
else {
|
||||
$g = " $g";
|
||||
$w = " $w";
|
||||
}
|
||||
$got = $got ? "$got\n$g" : $g;
|
||||
$wanted = $wanted ? "$wanted\n$w" : $w;
|
||||
}
|
||||
|
||||
return "$type is:\n" . "$got\nnot:\n$wanted\nas expected";
|
||||
}
|
||||
|
||||
##
|
||||
# forget all expected and got data
|
||||
|
||||
sub reset {
|
||||
my $self = shift;
|
||||
%$self = (
|
||||
type => $self->{type},
|
||||
got => '',
|
||||
wanted => [],
|
||||
);
|
||||
}
|
||||
|
||||
sub got {
|
||||
my $self = shift;
|
||||
return $self->{got};
|
||||
}
|
||||
|
||||
sub wanted {
|
||||
my $self = shift;
|
||||
return $self->{wanted};
|
||||
}
|
||||
|
||||
sub type {
|
||||
my $self = shift;
|
||||
return $self->{type};
|
||||
}
|
||||
|
||||
###
|
||||
# tie interface
|
||||
###
|
||||
|
||||
sub PRINT {
|
||||
my $self = shift;
|
||||
$self->{got} .= join '', @_;
|
||||
}
|
||||
|
||||
sub TIEHANDLE {
|
||||
my( $class, $type ) = @_;
|
||||
|
||||
my $self = bless { type => $type }, $class;
|
||||
|
||||
$self->reset;
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub READ { }
|
||||
sub READLINE { }
|
||||
sub GETC { }
|
||||
sub FILENO { }
|
||||
|
||||
1;
|
||||
51
database/perl/lib/Test/Builder/Tester/Color.pm
Normal file
51
database/perl/lib/Test/Builder/Tester/Color.pm
Normal file
@@ -0,0 +1,51 @@
|
||||
package Test::Builder::Tester::Color;
|
||||
|
||||
use strict;
|
||||
our $VERSION = '1.302183';
|
||||
|
||||
require Test::Builder::Tester;
|
||||
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Test::Builder::Tester::Color - turn on colour in Test::Builder::Tester
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
When running a test script
|
||||
|
||||
perl -MTest::Builder::Tester::Color test.t
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Importing this module causes the subroutine color in Test::Builder::Tester
|
||||
to be called with a true value causing colour highlighting to be turned
|
||||
on in debug output.
|
||||
|
||||
The sole purpose of this module is to enable colour highlighting
|
||||
from the command line.
|
||||
|
||||
=cut
|
||||
|
||||
sub import {
|
||||
Test::Builder::Tester::color(1);
|
||||
}
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Copyright Mark Fowler E<lt>mark@twoshortplanks.comE<gt> 2002.
|
||||
|
||||
This program is free software; you can redistribute it
|
||||
and/or modify it under the same terms as Perl itself.
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
This module will have no effect unless Term::ANSIColor is installed.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<Test::Builder::Tester>, L<Term::ANSIColor>
|
||||
|
||||
=cut
|
||||
|
||||
1;
|
||||
68
database/perl/lib/Test/Builder/TodoDiag.pm
Normal file
68
database/perl/lib/Test/Builder/TodoDiag.pm
Normal file
@@ -0,0 +1,68 @@
|
||||
package Test::Builder::TodoDiag;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '1.302183';
|
||||
|
||||
BEGIN { require Test2::Event::Diag; our @ISA = qw(Test2::Event::Diag) }
|
||||
|
||||
sub diagnostics { 0 }
|
||||
|
||||
sub facet_data {
|
||||
my $self = shift;
|
||||
my $out = $self->SUPER::facet_data();
|
||||
$out->{info}->[0]->{debug} = 0;
|
||||
return $out;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Test::Builder::TodoDiag - Test::Builder subclass of Test2::Event::Diag
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This is used to encapsulate diag messages created inside TODO.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
You do not need to use this directly.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Test2 can be found at
|
||||
F<http://github.com/Test-More/test-more/>.
|
||||
|
||||
=head1 MAINTAINERS
|
||||
|
||||
=over 4
|
||||
|
||||
=item Chad Granum E<lt>exodist@cpan.orgE<gt>
|
||||
|
||||
=back
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
=over 4
|
||||
|
||||
=item Chad Granum E<lt>exodist@cpan.orgE<gt>
|
||||
|
||||
=back
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright 2020 Chad Granum E<lt>exodist@cpan.orgE<gt>.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the same terms as Perl itself.
|
||||
|
||||
See F<http://dev.perl.org/licenses/>
|
||||
|
||||
=cut
|
||||
Reference in New Issue
Block a user