Initial Commit
This commit is contained in:
328
database/perl/vendor/lib/Test2/Compare/Array.pm
vendored
Normal file
328
database/perl/vendor/lib/Test2/Compare/Array.pm
vendored
Normal file
@@ -0,0 +1,328 @@
|
||||
package Test2::Compare::Array;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use base 'Test2::Compare::Base';
|
||||
|
||||
our $VERSION = '0.000139';
|
||||
|
||||
use Test2::Util::HashBase qw/inref meta ending items order for_each/;
|
||||
|
||||
use Carp qw/croak confess/;
|
||||
use Scalar::Util qw/reftype looks_like_number/;
|
||||
|
||||
sub init {
|
||||
my $self = shift;
|
||||
|
||||
if( defined( my $ref = $self->{+INREF}) ) {
|
||||
croak "Cannot specify both 'inref' and 'items'" if $self->{+ITEMS};
|
||||
croak "Cannot specify both 'inref' and 'order'" if $self->{+ORDER};
|
||||
croak "'inref' must be an array reference, got '$ref'" unless reftype($ref) eq 'ARRAY';
|
||||
my $order = $self->{+ORDER} = [];
|
||||
my $items = $self->{+ITEMS} = {};
|
||||
for (my $i = 0; $i < @$ref; $i++) {
|
||||
push @$order => $i;
|
||||
$items->{$i} = $ref->[$i];
|
||||
}
|
||||
}
|
||||
else {
|
||||
$self->{+ITEMS} ||= {};
|
||||
croak "All indexes listed in the 'items' hashref must be numeric"
|
||||
if grep { !looks_like_number($_) } keys %{$self->{+ITEMS}};
|
||||
|
||||
$self->{+ORDER} ||= [sort { $a <=> $b } keys %{$self->{+ITEMS}}];
|
||||
croak "All indexes listed in the 'order' arrayref must be numeric"
|
||||
if grep { !(looks_like_number($_) || (ref($_) && reftype($_) eq 'CODE')) } @{$self->{+ORDER}};
|
||||
}
|
||||
|
||||
$self->{+FOR_EACH} ||= [];
|
||||
|
||||
$self->SUPER::init();
|
||||
}
|
||||
|
||||
sub name { '<ARRAY>' }
|
||||
|
||||
sub meta_class { 'Test2::Compare::Meta' }
|
||||
|
||||
sub verify {
|
||||
my $self = shift;
|
||||
my %params = @_;
|
||||
|
||||
return 0 unless $params{exists};
|
||||
my $got = $params{got};
|
||||
return 0 unless defined $got;
|
||||
return 0 unless ref($got);
|
||||
return 0 unless reftype($got) eq 'ARRAY';
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub add_prop {
|
||||
my $self = shift;
|
||||
$self->{+META} = $self->meta_class->new unless defined $self->{+META};
|
||||
$self->{+META}->add_prop(@_);
|
||||
}
|
||||
|
||||
sub top_index {
|
||||
my $self = shift;
|
||||
my @order = @{$self->{+ORDER}};
|
||||
|
||||
while(@order) {
|
||||
my $idx = pop @order;
|
||||
next if ref $idx;
|
||||
return $idx;
|
||||
}
|
||||
|
||||
return undef; # No indexes
|
||||
}
|
||||
|
||||
sub add_item {
|
||||
my $self = shift;
|
||||
my $check = pop;
|
||||
my ($idx) = @_;
|
||||
|
||||
my $top = $self->top_index;
|
||||
|
||||
croak "elements must be added in order!"
|
||||
if $top && $idx && $idx <= $top;
|
||||
|
||||
$idx = defined($top) ? $top + 1 : 0
|
||||
unless defined($idx);
|
||||
|
||||
push @{$self->{+ORDER}} => $idx;
|
||||
$self->{+ITEMS}->{$idx} = $check;
|
||||
}
|
||||
|
||||
sub add_filter {
|
||||
my $self = shift;
|
||||
my ($code) = @_;
|
||||
croak "A single coderef is required"
|
||||
unless @_ == 1 && $code && ref $code && reftype($code) eq 'CODE';
|
||||
|
||||
push @{$self->{+ORDER}} => $code;
|
||||
}
|
||||
|
||||
sub add_for_each {
|
||||
my $self = shift;
|
||||
push @{$self->{+FOR_EACH}} => @_;
|
||||
}
|
||||
|
||||
sub deltas {
|
||||
my $self = shift;
|
||||
my %params = @_;
|
||||
my ($got, $convert, $seen) = @params{qw/got convert seen/};
|
||||
|
||||
my @deltas;
|
||||
my $state = 0;
|
||||
my @order = @{$self->{+ORDER}};
|
||||
my $items = $self->{+ITEMS};
|
||||
my $for_each = $self->{+FOR_EACH};
|
||||
|
||||
my $meta = $self->{+META};
|
||||
push @deltas => $meta->deltas(%params) if defined $meta;
|
||||
|
||||
# Make a copy that we can munge as needed.
|
||||
my @list = @$got;
|
||||
|
||||
while (@order) {
|
||||
my $idx = shift @order;
|
||||
my $overflow = 0;
|
||||
my $val;
|
||||
|
||||
# We have a filter, not an index
|
||||
if (ref($idx)) {
|
||||
@list = $idx->(@list);
|
||||
next;
|
||||
}
|
||||
|
||||
confess "Internal Error: Stacks are out of sync (state > idx)"
|
||||
if $state > $idx + 1;
|
||||
|
||||
while ($state <= $idx) {
|
||||
$overflow = !@list;
|
||||
$val = shift @list;
|
||||
|
||||
# check-all goes here so we hit each item, even unspecified ones.
|
||||
for my $check (@$for_each) {
|
||||
$check = $convert->($check);
|
||||
push @deltas => $check->run(
|
||||
id => [ARRAY => $state],
|
||||
convert => $convert,
|
||||
seen => $seen,
|
||||
exists => !$overflow,
|
||||
$overflow ? () : (got => $val),
|
||||
);
|
||||
}
|
||||
|
||||
$state++;
|
||||
}
|
||||
|
||||
confess "Internal Error: Stacks are out of sync (state != idx + 1)"
|
||||
unless $state == $idx + 1;
|
||||
|
||||
my $check = $convert->($items->{$idx});
|
||||
|
||||
push @deltas => $check->run(
|
||||
id => [ARRAY => $idx],
|
||||
convert => $convert,
|
||||
seen => $seen,
|
||||
exists => !$overflow,
|
||||
$overflow ? () : (got => $val),
|
||||
);
|
||||
}
|
||||
|
||||
while (@list && (@$for_each || $self->{+ENDING})) {
|
||||
my $item = shift @list;
|
||||
|
||||
for my $check (@$for_each) {
|
||||
$check = $convert->($check);
|
||||
push @deltas => $check->run(
|
||||
id => [ARRAY => $state],
|
||||
convert => $convert,
|
||||
seen => $seen,
|
||||
got => $item,
|
||||
exists => 1,
|
||||
);
|
||||
}
|
||||
|
||||
# if items are left over, and ending is true, we have a problem!
|
||||
if ($self->{+ENDING}) {
|
||||
push @deltas => $self->delta_class->new(
|
||||
dne => 'check',
|
||||
verified => undef,
|
||||
id => [ARRAY => $state],
|
||||
got => $item,
|
||||
check => undef,
|
||||
|
||||
$self->{+ENDING} eq 'implicit' ? (note => 'implicit end') : (),
|
||||
);
|
||||
}
|
||||
|
||||
$state++;
|
||||
}
|
||||
|
||||
return @deltas;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Test2::Compare::Array - Internal representation of an array comparison.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This module is an internal representation of an array for comparison purposes.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=over 4
|
||||
|
||||
=item $ref = $arr->inref()
|
||||
|
||||
If the instance was constructed from an actual array, this will return the
|
||||
reference to that array.
|
||||
|
||||
=item $bool = $arr->ending
|
||||
|
||||
=item $arr->set_ending($bool)
|
||||
|
||||
Set this to true if you would like to fail when the array being validated has
|
||||
more items than the check. That is, if you check indexes 0-3 but the array has
|
||||
values for indexes 0-4, it will fail and list that last item in the array as
|
||||
unexpected. If set to false then it is assumed you do not care about extra
|
||||
items.
|
||||
|
||||
=item $hashref = $arr->items()
|
||||
|
||||
Returns the hashref of C<< key => val >> pairs to be checked in the
|
||||
array.
|
||||
|
||||
=item $arr->set_items($hashref)
|
||||
|
||||
Accepts a hashref to permit indexes to be skipped if desired.
|
||||
|
||||
B<Note:> that there is no validation when using C<set_items>, it is better to
|
||||
use the C<add_item> interface.
|
||||
|
||||
=item $arrayref = $arr->order()
|
||||
|
||||
Returns an arrayref of all indexes that will be checked, in order.
|
||||
|
||||
=item $arr->set_order($arrayref)
|
||||
|
||||
Sets the order in which indexes will be checked.
|
||||
|
||||
B<Note:> that there is no validation when using C<set_order>, it is better to
|
||||
use the C<add_item> interface.
|
||||
|
||||
=item $name = $arr->name()
|
||||
|
||||
Always returns the string C<< "<ARRAY>" >>.
|
||||
|
||||
=item $bool = $arr->verify(got => $got, exists => $bool)
|
||||
|
||||
Check if C<$got> is an array reference or not.
|
||||
|
||||
=item $idx = $arr->top_index()
|
||||
|
||||
Returns the topmost index which is checked. This will return undef if there
|
||||
are no items, or C<0> if there is only 1 item.
|
||||
|
||||
=item $arr->add_item($item)
|
||||
|
||||
Push an item onto the list of values to be checked.
|
||||
|
||||
=item $arr->add_item($idx => $item)
|
||||
|
||||
Add an item to the list of values to be checked at the specified index.
|
||||
|
||||
=item $arr->add_filter(sub { ... })
|
||||
|
||||
Add a filter sub. The filter receives all remaining values of the array being
|
||||
checked, and should return the values that should still be checked. The filter
|
||||
will be run between the last item added and the next item added.
|
||||
|
||||
=item @deltas = $arr->deltas(got => $got, convert => \&convert, seen => \%seen)
|
||||
|
||||
Find the differences between the expected array values and those in the C<$got>
|
||||
arrayref.
|
||||
|
||||
=back
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Test2-Suite can be found at
|
||||
F<https://github.com/Test-More/Test2-Suite/>.
|
||||
|
||||
=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 2018 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
|
||||
244
database/perl/vendor/lib/Test2/Compare/Bag.pm
vendored
Normal file
244
database/perl/vendor/lib/Test2/Compare/Bag.pm
vendored
Normal file
@@ -0,0 +1,244 @@
|
||||
package Test2::Compare::Bag;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use base 'Test2::Compare::Base';
|
||||
|
||||
our $VERSION = '0.000139';
|
||||
|
||||
use Test2::Util::HashBase qw/ending meta items for_each/;
|
||||
|
||||
use Carp qw/croak confess/;
|
||||
use Scalar::Util qw/reftype looks_like_number/;
|
||||
|
||||
sub init {
|
||||
my $self = shift;
|
||||
|
||||
$self->{+ITEMS} ||= [];
|
||||
$self->{+FOR_EACH} ||= [];
|
||||
|
||||
$self->SUPER::init();
|
||||
}
|
||||
|
||||
sub name { '<BAG>' }
|
||||
|
||||
sub meta_class { 'Test2::Compare::Meta' }
|
||||
|
||||
sub verify {
|
||||
my $self = shift;
|
||||
my %params = @_;
|
||||
|
||||
return 0 unless $params{exists};
|
||||
my $got = $params{got} || return 0;
|
||||
return 0 unless ref($got);
|
||||
return 0 unless reftype($got) eq 'ARRAY';
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub add_prop {
|
||||
my $self = shift;
|
||||
$self->{+META} = $self->meta_class->new unless defined $self->{+META};
|
||||
$self->{+META}->add_prop(@_);
|
||||
}
|
||||
|
||||
sub add_item {
|
||||
my $self = shift;
|
||||
my $check = pop;
|
||||
my ($idx) = @_;
|
||||
|
||||
push @{$self->{+ITEMS}}, $check;
|
||||
}
|
||||
|
||||
sub add_for_each {
|
||||
my $self = shift;
|
||||
push @{$self->{+FOR_EACH}} => @_;
|
||||
}
|
||||
|
||||
sub deltas {
|
||||
my $self = shift;
|
||||
my %params = @_;
|
||||
my ($got, $convert, $seen) = @params{qw/got convert seen/};
|
||||
|
||||
my @deltas;
|
||||
my $state = 0;
|
||||
my @items = @{$self->{+ITEMS}};
|
||||
my @for_each = @{$self->{+FOR_EACH}};
|
||||
|
||||
# Make a copy that we can munge as needed.
|
||||
my @list = @$got;
|
||||
my %unmatched = map { $_ => $list[$_] } 0..$#list;
|
||||
|
||||
my $meta = $self->{+META};
|
||||
push @deltas => $meta->deltas(%params) if defined $meta;
|
||||
|
||||
while (@items) {
|
||||
my $item = shift @items;
|
||||
|
||||
my $check = $convert->($item);
|
||||
|
||||
my $match = 0;
|
||||
for my $idx (0..$#list) {
|
||||
next unless exists $unmatched{$idx};
|
||||
my $val = $list[$idx];
|
||||
my $deltas = $check->run(
|
||||
id => [ARRAY => $idx],
|
||||
convert => $convert,
|
||||
seen => $seen,
|
||||
exists => 1,
|
||||
got => $val,
|
||||
);
|
||||
|
||||
unless ($deltas) {
|
||||
$match++;
|
||||
delete $unmatched{$idx};
|
||||
last;
|
||||
}
|
||||
}
|
||||
unless ($match) {
|
||||
push @deltas => $self->delta_class->new(
|
||||
dne => 'got',
|
||||
verified => undef,
|
||||
id => [ARRAY => '*'],
|
||||
got => undef,
|
||||
check => $check,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (@for_each) {
|
||||
my @checks = map { $convert->($_) } @for_each;
|
||||
|
||||
for my $idx (0..$#list) {
|
||||
# All items are matched if we have conditions for all items
|
||||
delete $unmatched{$idx};
|
||||
|
||||
my $val = $list[$idx];
|
||||
|
||||
for my $check (@checks) {
|
||||
push @deltas => $check->run(
|
||||
id => [ARRAY => $idx],
|
||||
convert => $convert,
|
||||
seen => $seen,
|
||||
exists => 1,
|
||||
got => $val,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# if elements are left over, and ending is true, we have a problem!
|
||||
if($self->{+ENDING} && keys %unmatched) {
|
||||
for my $idx (sort keys %unmatched) {
|
||||
my $elem = $list[$idx];
|
||||
push @deltas => $self->delta_class->new(
|
||||
dne => 'check',
|
||||
verified => undef,
|
||||
id => [ARRAY => $idx],
|
||||
got => $elem,
|
||||
check => undef,
|
||||
|
||||
$self->{+ENDING} eq 'implicit' ? (note => 'implicit end') : (),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return @deltas;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Test2::Compare::Bag - Internal representation of a bag comparison.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This module is an internal representation of a bag for comparison purposes.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=over 4
|
||||
|
||||
=item $bool = $arr->ending
|
||||
|
||||
=item $arr->set_ending($bool)
|
||||
|
||||
Set this to true if you would like to fail when the array being validated has
|
||||
more items than the check. That is, if you check for 4 items but the array has
|
||||
5 values, it will fail and list that unmatched item in the array as
|
||||
unexpected. If set to false then it is assumed you do not care about extra
|
||||
items.
|
||||
|
||||
=item $arrayref = $arr->items()
|
||||
|
||||
Returns the arrayref of values to be checked in the array.
|
||||
|
||||
=item $arr->set_items($arrayref)
|
||||
|
||||
Accepts an arrayref.
|
||||
|
||||
B<Note:> that there is no validation when using C<set_items>, it is better to
|
||||
use the C<add_item> interface.
|
||||
|
||||
=item $name = $arr->name()
|
||||
|
||||
Always returns the string C<< "<BAG>" >>.
|
||||
|
||||
=item $bool = $arr->verify(got => $got, exists => $bool)
|
||||
|
||||
Check if C<$got> is an array reference or not.
|
||||
|
||||
=item $arr->add_item($item)
|
||||
|
||||
Push an item onto the list of values to be checked.
|
||||
|
||||
=item @deltas = $arr->deltas(got => $got, convert => \&convert, seen => \%seen)
|
||||
|
||||
Find the differences between the expected bag values and those in the C<$got>
|
||||
arrayref.
|
||||
|
||||
=back
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Test2-Suite can be found at
|
||||
F<https://github.com/Test-More/Test2-Suite/>.
|
||||
|
||||
=head1 MAINTAINERS
|
||||
|
||||
=over 4
|
||||
|
||||
=item Chad Granum E<lt>exodist@cpan.orgE<gt>
|
||||
|
||||
=item Gianni Ceccarelli E<lt>dakkar@thenautilus.netE<gt>
|
||||
|
||||
=back
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
=over 4
|
||||
|
||||
=item Chad Granum E<lt>exodist@cpan.orgE<gt>
|
||||
|
||||
=item Gianni Ceccarelli E<lt>dakkar@thenautilus.netE<gt>
|
||||
|
||||
=back
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>.
|
||||
|
||||
Copyright 2018 Gianni Ceccarelli E<lt>dakkar@thenautilus.netE<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
|
||||
252
database/perl/vendor/lib/Test2/Compare/Base.pm
vendored
Normal file
252
database/perl/vendor/lib/Test2/Compare/Base.pm
vendored
Normal file
@@ -0,0 +1,252 @@
|
||||
package Test2::Compare::Base;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.000139';
|
||||
|
||||
use Carp qw/confess croak/;
|
||||
use Scalar::Util qw/blessed/;
|
||||
|
||||
use Sub::Info qw/sub_info/;
|
||||
use Test2::Compare::Delta();
|
||||
|
||||
sub MAX_CYCLES() { 75 }
|
||||
|
||||
use Test2::Util::HashBase qw{builder _file _lines _info called};
|
||||
use Test2::Util::Ref qw/render_ref/;
|
||||
|
||||
{
|
||||
no warnings 'once';
|
||||
*set_lines = \&set__lines;
|
||||
*set_file = \&set__file;
|
||||
}
|
||||
|
||||
sub clone {
|
||||
my $self = shift;
|
||||
my $class = blessed($self);
|
||||
|
||||
# Shallow copy is good enough for all the current compare types.
|
||||
return bless({%$self}, $class);
|
||||
}
|
||||
|
||||
sub init {
|
||||
my $self = shift;
|
||||
$self->{+_LINES} = delete $self->{lines} if exists $self->{lines};
|
||||
$self->{+_FILE} = delete $self->{file} if exists $self->{file};
|
||||
}
|
||||
|
||||
sub file {
|
||||
my $self = shift;
|
||||
return $self->{+_FILE} if $self->{+_FILE};
|
||||
|
||||
if ($self->{+BUILDER}) {
|
||||
$self->{+_INFO} ||= sub_info($self->{+BUILDER});
|
||||
return $self->{+_INFO}->{file};
|
||||
}
|
||||
elsif ($self->{+CALLED}) {
|
||||
return $self->{+CALLED}->[1];
|
||||
}
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub lines {
|
||||
my $self = shift;
|
||||
return $self->{+_LINES} if $self->{+_LINES};
|
||||
|
||||
if ($self->{+BUILDER}) {
|
||||
$self->{+_INFO} ||= sub_info($self->{+BUILDER});
|
||||
return $self->{+_INFO}->{lines} if @{$self->{+_INFO}->{lines}};
|
||||
}
|
||||
if ($self->{+CALLED}) {
|
||||
return [$self->{+CALLED}->[2]];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
sub delta_class { 'Test2::Compare::Delta' }
|
||||
|
||||
sub deltas { () }
|
||||
sub got_lines { () }
|
||||
|
||||
sub stringify_got { 0 }
|
||||
|
||||
sub operator { '' }
|
||||
sub verify { confess "unimplemented" }
|
||||
sub name { confess "unimplemented" }
|
||||
|
||||
sub render {
|
||||
my $self = shift;
|
||||
return $self->name;
|
||||
}
|
||||
|
||||
sub run {
|
||||
my $self = shift;
|
||||
my %params = @_;
|
||||
|
||||
my $id = $params{id};
|
||||
my $convert = $params{convert} or confess "no convert sub provided";
|
||||
my $seen = $params{seen} ||= {};
|
||||
|
||||
$params{exists} = exists $params{got} ? 1 : 0
|
||||
unless exists $params{exists};
|
||||
|
||||
my $exists = $params{exists};
|
||||
my $got = $exists ? $params{got} : undef;
|
||||
|
||||
my $gotname = render_ref($got);
|
||||
|
||||
# Prevent infinite cycles
|
||||
if (defined($got) && ref $got) {
|
||||
die "Cycle detected in comparison, aborting"
|
||||
if $seen->{$gotname} && $seen->{$gotname} >= MAX_CYCLES;
|
||||
$seen->{$gotname}++;
|
||||
}
|
||||
|
||||
my $ok = $self->verify(%params);
|
||||
my @deltas = $ok ? $self->deltas(%params) : ();
|
||||
|
||||
$seen->{$gotname}-- if defined $got && ref $got;
|
||||
|
||||
return if $ok && !@deltas;
|
||||
|
||||
return $self->delta_class->new(
|
||||
verified => $ok,
|
||||
id => $id,
|
||||
got => $got,
|
||||
check => $self,
|
||||
children => \@deltas,
|
||||
$exists ? () : (dne => 'got'),
|
||||
);
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Test2::Compare::Base - Base class for comparison classes.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
All comparison classes for Test2::Compare should inherit from this base class.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
package Test2::Compare::MyCheck;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use base 'Test2::Compare::Base';
|
||||
use Test2::Util::HashBase qw/stuff/;
|
||||
|
||||
sub name { 'STUFF' }
|
||||
|
||||
sub operator {
|
||||
my $self = shift;
|
||||
my ($got) = @_;
|
||||
return 'eq';
|
||||
}
|
||||
|
||||
sub verify {
|
||||
my $self = shift;
|
||||
my $params = @_;
|
||||
|
||||
# Always check if $got exists! This method must return false if no
|
||||
# value at all was received.
|
||||
return 0 unless $params{exists};
|
||||
|
||||
my $got = $params{got};
|
||||
|
||||
# Returns true if both values match. This includes undef, 0, and other
|
||||
# false-y values!
|
||||
return $got eq $self->stuff;
|
||||
}
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
Some of these must be overridden, others can be.
|
||||
|
||||
=over 4
|
||||
|
||||
=item $dclass = $check->delta_class
|
||||
|
||||
Returns the delta subclass that should be used. By default
|
||||
L<Test2::Compare::Delta> is used.
|
||||
|
||||
=item @deltas = $check->deltas(id => $id, exists => $bool, got => $got, convert => \&convert, seen => \%seen)
|
||||
|
||||
Should return child deltas.
|
||||
|
||||
=item @lines = $check->got_lines($got)
|
||||
|
||||
This is your chance to provide line numbers for errors in the C<$got>
|
||||
structure.
|
||||
|
||||
=item $op = $check->operator()
|
||||
|
||||
=item $op = $check->operator($got)
|
||||
|
||||
Returns the operator that was used to compare the check with the received data
|
||||
in C<$got>. If there was no value for got then there will be no arguments,
|
||||
undef will only be an argument if undef was seen in C<$got>. This is how you
|
||||
can tell the difference between a missing value and an undefined one.
|
||||
|
||||
=item $bool = $check->verify(id => $id, exists => $bool, got => $got, convert => \&convert, seen => \%seen)
|
||||
|
||||
Return true if there is a shallow match, that is both items are arrayrefs, both
|
||||
items are the same string or same number, etc. This should not recurse, as deep
|
||||
checks are done in C<< $check->deltas() >>.
|
||||
|
||||
=item $name = $check->name
|
||||
|
||||
Get the name of the check.
|
||||
|
||||
=item $display = $check->render
|
||||
|
||||
What should be displayed in a table for this check, usually the name or value.
|
||||
|
||||
=item $delta = $check->run(id => $id, exists => $bool, got => $got, convert => \&convert, seen => \%seen)
|
||||
|
||||
This is where the checking is done, first a shallow check using
|
||||
C<< $check->verify >>, then checking C<< $check->deltas() >>. C<\%seen> is used
|
||||
to prevent cycles.
|
||||
|
||||
=back
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Test2-Suite can be found at
|
||||
F<https://github.com/Test-More/Test2-Suite/>.
|
||||
|
||||
=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 2018 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
|
||||
111
database/perl/vendor/lib/Test2/Compare/Bool.pm
vendored
Normal file
111
database/perl/vendor/lib/Test2/Compare/Bool.pm
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
package Test2::Compare::Bool;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Carp qw/confess/;
|
||||
|
||||
use base 'Test2::Compare::Base';
|
||||
|
||||
our $VERSION = '0.000139';
|
||||
|
||||
use Test2::Util::HashBase qw/input/;
|
||||
|
||||
# Overloads '!' for us.
|
||||
use Test2::Compare::Negatable;
|
||||
|
||||
sub name {
|
||||
my $self = shift;
|
||||
my $in = $self->{+INPUT};
|
||||
return _render_bool($in);
|
||||
}
|
||||
|
||||
sub operator {
|
||||
my $self = shift;
|
||||
return '!=' if $self->{+NEGATE};
|
||||
return '==';
|
||||
}
|
||||
|
||||
sub verify {
|
||||
my $self = shift;
|
||||
my %params = @_;
|
||||
my ($got, $exists) = @params{qw/got exists/};
|
||||
|
||||
return 0 unless $exists;
|
||||
|
||||
my $want = $self->{+INPUT};
|
||||
|
||||
my $match = ($want xor $got) ? 0 : 1;
|
||||
$match = $match ? 0 : 1 if $self->{+NEGATE};
|
||||
|
||||
return $match;
|
||||
}
|
||||
|
||||
sub run {
|
||||
my $self = shift;
|
||||
my $delta = $self->SUPER::run(@_) or return;
|
||||
|
||||
my $dne = $delta->dne || "";
|
||||
unless ($dne eq 'got') {
|
||||
my $got = $delta->got;
|
||||
$delta->set_got(_render_bool($got));
|
||||
}
|
||||
|
||||
return $delta;
|
||||
}
|
||||
|
||||
sub _render_bool {
|
||||
my $bool = shift;
|
||||
my $name = $bool ? 'TRUE' : 'FALSE';
|
||||
my $val = defined $bool ? $bool : 'undef';
|
||||
$val = "''" unless length($val);
|
||||
|
||||
return "<$name ($val)>";
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Test2::Compare::Bool - Compare two values as booleans
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Check if two values have the same boolean result (both true, or both false).
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Test2-Suite can be found at
|
||||
F<https://github.com/Test-More/Test2-Suite/>.
|
||||
|
||||
=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 2018 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
|
||||
173
database/perl/vendor/lib/Test2/Compare/Custom.pm
vendored
Normal file
173
database/perl/vendor/lib/Test2/Compare/Custom.pm
vendored
Normal file
@@ -0,0 +1,173 @@
|
||||
package Test2::Compare::Custom;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use base 'Test2::Compare::Base';
|
||||
|
||||
our $VERSION = '0.000139';
|
||||
|
||||
use Test2::Util::HashBase qw/code name operator/;
|
||||
|
||||
use Carp qw/croak/;
|
||||
|
||||
sub init {
|
||||
my $self = shift;
|
||||
|
||||
croak "'code' is required" unless $self->{+CODE};
|
||||
|
||||
$self->{+OPERATOR} ||= 'CODE(...)';
|
||||
$self->{+NAME} ||= '<Custom Code>';
|
||||
|
||||
$self->SUPER::init();
|
||||
}
|
||||
|
||||
sub verify {
|
||||
my $self = shift;
|
||||
my %params = @_;
|
||||
my ($got, $exists) = @params{qw/got exists/};
|
||||
|
||||
my $code = $self->{+CODE};
|
||||
|
||||
local $_ = $got;
|
||||
my $ok = $code->(
|
||||
got => $got,
|
||||
exists => $exists,
|
||||
operator => $self->{+OPERATOR},
|
||||
name => $self->{+NAME},
|
||||
);
|
||||
|
||||
return $ok;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Test2::Compare::Custom - Custom field check for comparisons.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Sometimes you want to do something complicated or unusual when validating a
|
||||
field nested inside a deep data structure. You could pull it out of the
|
||||
structure and test it separately, or you can use this to embed the check. This
|
||||
provides a way for you to write custom checks for fields in deep comparisons.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
my $cus = Test2::Compare::Custom->new(
|
||||
name => 'IsRef',
|
||||
operator => 'ref(...)',
|
||||
code => sub {
|
||||
my %args = @_;
|
||||
return $args{got} ? 1 : 0;
|
||||
},
|
||||
);
|
||||
|
||||
# Pass
|
||||
is(
|
||||
{ a => 1, ref => {}, b => 2 },
|
||||
{ a => 1, ref => $cus, b => 2 },
|
||||
"This will pass"
|
||||
);
|
||||
|
||||
# Fail
|
||||
is(
|
||||
{a => 1, ref => 'notref', b => 2},
|
||||
{a => 1, ref => $cus, b => 2},
|
||||
"This will fail"
|
||||
);
|
||||
|
||||
=head1 ARGUMENTS
|
||||
|
||||
Your custom sub will be passed 4 arguments in a hash:
|
||||
|
||||
code => sub {
|
||||
my %args = @_;
|
||||
# provides got, exists, operator, name
|
||||
return ref($args{got}) ? 1 : 0;
|
||||
},
|
||||
|
||||
C<$_> is also localized to C<got> to make it easier for those who need to use
|
||||
regexes.
|
||||
|
||||
=over 4
|
||||
|
||||
=item got
|
||||
|
||||
=item $_
|
||||
|
||||
The value to be checked.
|
||||
|
||||
=item exists
|
||||
|
||||
This will be a boolean. This will be true if C<got> exists at all. If
|
||||
C<exists> is false then it means C<got> is not simply undef, but doesn't
|
||||
exist at all (think checking the value of a hash key that does not exist).
|
||||
|
||||
=item operator
|
||||
|
||||
The operator specified at construction.
|
||||
|
||||
=item name
|
||||
|
||||
The name provided at construction.
|
||||
|
||||
=back
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=over 4
|
||||
|
||||
=item $code = $cus->code
|
||||
|
||||
Returns the coderef provided at construction.
|
||||
|
||||
=item $name = $cus->name
|
||||
|
||||
Returns the name provided at construction.
|
||||
|
||||
=item $op = $cus->operator
|
||||
|
||||
Returns the operator provided at construction.
|
||||
|
||||
=item $bool = $cus->verify(got => $got, exists => $bool)
|
||||
|
||||
=back
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Test2-Suite can be found at
|
||||
F<https://github.com/Test-More/Test2-Suite/>.
|
||||
|
||||
=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 2018 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
|
||||
119
database/perl/vendor/lib/Test2/Compare/DeepRef.pm
vendored
Normal file
119
database/perl/vendor/lib/Test2/Compare/DeepRef.pm
vendored
Normal file
@@ -0,0 +1,119 @@
|
||||
package Test2::Compare::DeepRef;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use base 'Test2::Compare::Base';
|
||||
|
||||
our $VERSION = '0.000139';
|
||||
|
||||
use Test2::Util::HashBase qw/input/;
|
||||
|
||||
use Test2::Util::Ref qw/render_ref rtype/;
|
||||
use Scalar::Util qw/refaddr/;
|
||||
use Carp qw/croak/;
|
||||
|
||||
sub init {
|
||||
my $self = shift;
|
||||
|
||||
croak "'input' is a required attribute"
|
||||
unless $self->{+INPUT};
|
||||
|
||||
croak "'input' must be a reference, got '" . $self->{+INPUT} . "'"
|
||||
unless ref $self->{+INPUT};
|
||||
|
||||
$self->SUPER::init();
|
||||
}
|
||||
|
||||
sub name { '<REF>' }
|
||||
|
||||
sub verify {
|
||||
my $self = shift;
|
||||
my %params = @_;
|
||||
my ($got, $exists) = @params{qw/got exists/};
|
||||
|
||||
return 0 unless $exists;
|
||||
|
||||
my $in = $self->{+INPUT};
|
||||
return 0 unless ref $in;
|
||||
return 0 unless ref $got;
|
||||
|
||||
my $in_type = rtype($in);
|
||||
my $got_type = rtype($got);
|
||||
|
||||
return 0 unless $in_type eq $got_type;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub deltas {
|
||||
my $self = shift;
|
||||
my %params = @_;
|
||||
my ($got, $convert, $seen) = @params{qw/got convert seen/};
|
||||
|
||||
my $in = $self->{+INPUT};
|
||||
my $in_type = rtype($in);
|
||||
my $got_type = rtype($got);
|
||||
|
||||
my $check = $convert->($$in);
|
||||
|
||||
return $check->run(
|
||||
id => ['DEREF' => '$*'],
|
||||
convert => $convert,
|
||||
seen => $seen,
|
||||
got => $$got,
|
||||
exists => 1,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Test2::Compare::DeepRef - Ref comparison
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Used to compare two refs in a deep comparison.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Test2-Suite can be found at
|
||||
F<https://github.com/Test-More/Test2-Suite/>.
|
||||
|
||||
=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 2018 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
|
||||
558
database/perl/vendor/lib/Test2/Compare/Delta.pm
vendored
Normal file
558
database/perl/vendor/lib/Test2/Compare/Delta.pm
vendored
Normal file
@@ -0,0 +1,558 @@
|
||||
package Test2::Compare::Delta;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.000139';
|
||||
|
||||
use Test2::Util::HashBase qw{verified id got chk children dne exception note};
|
||||
|
||||
use Test2::EventFacet::Info::Table;
|
||||
|
||||
use Test2::Util::Table();
|
||||
use Test2::API qw/context/;
|
||||
|
||||
use Test2::Util::Ref qw/render_ref rtype/;
|
||||
use Carp qw/croak/;
|
||||
|
||||
# 'CHECK' constant would not work, but I like exposing 'check()' to people
|
||||
# using this class.
|
||||
BEGIN {
|
||||
no warnings 'once';
|
||||
*check = \&chk;
|
||||
*set_check = \&set_chk;
|
||||
}
|
||||
|
||||
my @COLUMN_ORDER = qw/PATH GLNs GOT OP CHECK CLNs/;
|
||||
my %COLUMNS = (
|
||||
GOT => {name => 'GOT', value => sub { $_[0]->render_got }, no_collapse => 1},
|
||||
CHECK => {name => 'CHECK', value => sub { $_[0]->render_check }, no_collapse => 1},
|
||||
OP => {name => 'OP', value => sub { $_[0]->table_op } },
|
||||
PATH => {name => 'PATH', value => sub { $_[1] } },
|
||||
|
||||
'GLNs' => {name => 'GLNs', alias => 'LNs', value => sub { $_[0]->table_got_lines } },
|
||||
'CLNs' => {name => 'CLNs', alias => 'LNs', value => sub { $_[0]->table_check_lines }},
|
||||
);
|
||||
{
|
||||
my $i = 0;
|
||||
$COLUMNS{$_}->{id} = $i++ for @COLUMN_ORDER;
|
||||
}
|
||||
|
||||
sub remove_column {
|
||||
my $class = shift;
|
||||
my $header = shift;
|
||||
@COLUMN_ORDER = grep { $_ ne $header } @COLUMN_ORDER;
|
||||
delete $COLUMNS{$header} ? 1 : 0;
|
||||
}
|
||||
|
||||
sub add_column {
|
||||
my $class = shift;
|
||||
my $name = shift;
|
||||
|
||||
croak "Column name is required"
|
||||
unless $name;
|
||||
|
||||
croak "Column '$name' is already defined"
|
||||
if $COLUMNS{$name};
|
||||
|
||||
my %params;
|
||||
if (@_ == 1) {
|
||||
%params = (value => @_, name => $name);
|
||||
}
|
||||
else {
|
||||
%params = (@_, name => $name);
|
||||
}
|
||||
|
||||
my $value = $params{value};
|
||||
|
||||
croak "You must specify a 'value' callback"
|
||||
unless $value;
|
||||
|
||||
croak "'value' callback must be a CODE reference"
|
||||
unless rtype($value) eq 'CODE';
|
||||
|
||||
if ($params{prefix}) {
|
||||
unshift @COLUMN_ORDER => $name;
|
||||
}
|
||||
else {
|
||||
push @COLUMN_ORDER => $name;
|
||||
}
|
||||
|
||||
$COLUMNS{$name} = \%params;
|
||||
}
|
||||
|
||||
sub set_column_alias {
|
||||
my ($class, $name, $alias) = @_;
|
||||
|
||||
croak "Tried to alias a non-existent column"
|
||||
unless exists $COLUMNS{$name};
|
||||
|
||||
croak "Missing alias" unless defined $alias;
|
||||
|
||||
$COLUMNS{$name}->{alias} = $alias;
|
||||
}
|
||||
|
||||
sub init {
|
||||
my $self = shift;
|
||||
|
||||
croak "Cannot specify both 'check' and 'chk' as arguments"
|
||||
if exists($self->{check}) && exists($self->{+CHK});
|
||||
|
||||
# Allow 'check' as an argument
|
||||
$self->{+CHK} ||= delete $self->{check}
|
||||
if exists $self->{check};
|
||||
}
|
||||
|
||||
sub render_got {
|
||||
my $self = shift;
|
||||
|
||||
my $exp = $self->{+EXCEPTION};
|
||||
if ($exp) {
|
||||
chomp($exp = "$exp");
|
||||
$exp =~ s/\n.*$//g;
|
||||
return "<EXCEPTION: $exp>";
|
||||
}
|
||||
|
||||
my $dne = $self->{+DNE};
|
||||
return '<DOES NOT EXIST>' if $dne && $dne eq 'got';
|
||||
|
||||
my $got = $self->{+GOT};
|
||||
return '<UNDEF>' unless defined $got;
|
||||
|
||||
my $check = $self->{+CHK};
|
||||
my $stringify = defined( $check ) && $check->stringify_got;
|
||||
|
||||
return render_ref($got) if ref $got && !$stringify;
|
||||
|
||||
return "$got";
|
||||
}
|
||||
|
||||
sub render_check {
|
||||
my $self = shift;
|
||||
|
||||
my $dne = $self->{+DNE};
|
||||
return '<DOES NOT EXIST>' if $dne && $dne eq 'check';
|
||||
|
||||
my $check = $self->{+CHK};
|
||||
return '<UNDEF>' unless defined $check;
|
||||
|
||||
return $check->render;
|
||||
}
|
||||
|
||||
sub _full_id {
|
||||
my ($type, $id) = @_;
|
||||
return "<$id>" if !$type || $type eq 'META';
|
||||
return $id if $type eq 'SCALAR';
|
||||
return "{$id}" if $type eq 'HASH';
|
||||
return "{$id} <KEY>" if $type eq 'HASHKEY';
|
||||
return "[$id]" if $type eq 'ARRAY';
|
||||
return "$id()" if $type eq 'METHOD';
|
||||
return "$id" if $type eq 'DEREF';
|
||||
return "<$id>";
|
||||
}
|
||||
|
||||
sub _arrow_id {
|
||||
my ($path, $type) = @_;
|
||||
return '' unless $path;
|
||||
|
||||
return ' ' if !$type || $type eq 'META'; # Meta gets a space, not an arrow
|
||||
|
||||
return '->' if $type eq 'METHOD'; # Method always needs an arrow
|
||||
return '->' if $type eq 'SCALAR'; # Scalar always needs an arrow
|
||||
return '->' if $type eq 'DEREF'; # deref always needs arrow
|
||||
return '->' if $path =~ m/(>|\(\))$/; # Need an arrow after meta, or after a method
|
||||
return '->' if $path eq '$VAR'; # Need an arrow after the initial ref
|
||||
|
||||
# Hash and array need an arrow unless they follow another hash/array
|
||||
return '->' if $type =~ m/^(HASH|ARRAY)$/ && $path !~ m/(\]|\})$/;
|
||||
|
||||
# No arrow needed
|
||||
return '';
|
||||
}
|
||||
|
||||
sub _join_id {
|
||||
my ($path, $parts) = @_;
|
||||
my ($type, $key) = @$parts;
|
||||
|
||||
my $id = _full_id($type, $key);
|
||||
my $join = _arrow_id($path, $type);
|
||||
|
||||
return "${path}${join}${id}";
|
||||
}
|
||||
|
||||
sub should_show {
|
||||
my $self = shift;
|
||||
return 1 unless $self->verified;
|
||||
defined( my $check = $self->check ) || return 0;
|
||||
return 0 unless $check->lines;
|
||||
my $file = $check->file || return 0;
|
||||
|
||||
my $ctx = context();
|
||||
my $cfile = $ctx->trace->file;
|
||||
$ctx->release;
|
||||
return 0 unless $file eq $cfile;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub filter_visible {
|
||||
my $self = shift;
|
||||
|
||||
my @deltas;
|
||||
my @queue = (['', $self]);
|
||||
|
||||
while (my $set = shift @queue) {
|
||||
my ($path, $delta) = @$set;
|
||||
|
||||
push @deltas => [$path, $delta] if $delta->should_show;
|
||||
|
||||
my $children = $delta->children || next;
|
||||
next unless @$children;
|
||||
|
||||
my @new;
|
||||
for my $child (@$children) {
|
||||
my $cpath = _join_id($path, $child->id);
|
||||
push @new => [$cpath, $child];
|
||||
}
|
||||
unshift @queue => @new;
|
||||
}
|
||||
|
||||
return \@deltas;
|
||||
}
|
||||
|
||||
sub table_header { [map {$COLUMNS{$_}->{alias} || $_} @COLUMN_ORDER] }
|
||||
|
||||
sub table_op {
|
||||
my $self = shift;
|
||||
|
||||
defined( my $check = $self->{+CHK} ) || return '!exists';
|
||||
|
||||
return $check->operator($self->{+GOT})
|
||||
unless $self->{+DNE} && $self->{+DNE} eq 'got';
|
||||
|
||||
return $check->operator();
|
||||
}
|
||||
|
||||
sub table_check_lines {
|
||||
my $self = shift;
|
||||
|
||||
defined( my $check = $self->{+CHK} ) || return '';
|
||||
my $lines = $check->lines || return '';
|
||||
|
||||
return '' unless @$lines;
|
||||
|
||||
return join ', ' => @$lines;
|
||||
}
|
||||
|
||||
sub table_got_lines {
|
||||
my $self = shift;
|
||||
|
||||
defined( my $check = $self->{+CHK} ) || return '';
|
||||
return '' if $self->{+DNE} && $self->{+DNE} eq 'got';
|
||||
|
||||
my @lines = $check->got_lines($self->{+GOT});
|
||||
return '' unless @lines;
|
||||
|
||||
return join ', ' => @lines;
|
||||
}
|
||||
|
||||
sub table_rows {
|
||||
my $self = shift;
|
||||
|
||||
my $deltas = $self->filter_visible;
|
||||
|
||||
my @rows;
|
||||
for my $set (@$deltas) {
|
||||
my ($id, $d) = @$set;
|
||||
|
||||
my @row;
|
||||
for my $col (@COLUMN_ORDER) {
|
||||
my $spec = $COLUMNS{$col};
|
||||
my $val = $spec->{value}->($d, $id);
|
||||
$val = '' unless defined $val;
|
||||
push @row => $val;
|
||||
}
|
||||
|
||||
push @rows => \@row;
|
||||
}
|
||||
|
||||
return \@rows;
|
||||
}
|
||||
|
||||
sub table {
|
||||
my $self = shift;
|
||||
|
||||
my @diag;
|
||||
my $header = $self->table_header;
|
||||
my $rows = $self->table_rows;
|
||||
|
||||
my $render_rows = [@$rows];
|
||||
my $max = exists $ENV{TS_MAX_DELTA} ? $ENV{TS_MAX_DELTA} : 25;
|
||||
if ($max && @$render_rows > $max) {
|
||||
@$render_rows = map { [@$_] } @{$render_rows}[0 .. ($max - 1)];
|
||||
@diag = (
|
||||
"************************************************************",
|
||||
sprintf("* Stopped after %-42.42s *", "$max differences."),
|
||||
"* Set the TS_MAX_DELTA environment var to raise the limit. *",
|
||||
"* Set it to 0 for no limit. *",
|
||||
"************************************************************",
|
||||
);
|
||||
}
|
||||
|
||||
my @dne;
|
||||
for my $row (@$render_rows) {
|
||||
my $got = $row->[$COLUMNS{GOT}->{id}] || '';
|
||||
my $chk = $row->[$COLUMNS{CHECK}->{id}] || '';
|
||||
if ($got eq '<DOES NOT EXIST>') {
|
||||
push @dne => "$row->[$COLUMNS{PATH}->{id}]: DOES NOT EXIST";
|
||||
}
|
||||
elsif ($chk eq '<DOES NOT EXIST>') {
|
||||
push @dne => "$row->[$COLUMNS{PATH}->{id}]: SHOULD NOT EXIST";
|
||||
}
|
||||
}
|
||||
|
||||
if (@dne) {
|
||||
unshift @dne => '==== Summary of missing/extra items ====';
|
||||
push @dne => '== end summary of missing/extra items ==';
|
||||
}
|
||||
|
||||
my $table_args = {
|
||||
header => $header,
|
||||
collapse => 1,
|
||||
sanitize => 1,
|
||||
mark_tail => 1,
|
||||
no_collapse => [grep { $COLUMNS{$COLUMN_ORDER[$_]}->{no_collapse} } 0 .. $#COLUMN_ORDER],
|
||||
};
|
||||
|
||||
my $render = join "\n" => (
|
||||
Test2::Util::Table::table(%$table_args, rows => $render_rows),
|
||||
@dne,
|
||||
@diag,
|
||||
);
|
||||
|
||||
my $table = Test2::EventFacet::Info::Table->new(
|
||||
%$table_args,
|
||||
rows => $rows,
|
||||
as_string => $render,
|
||||
);
|
||||
|
||||
return $table;
|
||||
}
|
||||
|
||||
sub diag { shift->table }
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Test2::Compare::Delta - Representation of differences between nested data
|
||||
structures.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This is used by L<Test2::Compare>. When data structures are compared a
|
||||
delta will be returned. Deltas are a tree data structure that represent all the
|
||||
differences between two other data structures.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=head2 CLASS METHODS
|
||||
|
||||
=over 4
|
||||
|
||||
=item $class->add_column($NAME => sub { ... })
|
||||
|
||||
=item $class->add_column($NAME, %PARAMS)
|
||||
|
||||
This can be used to add columns to the table that it produced when a comparison
|
||||
fails. The first argument should always be the column name, which must be
|
||||
unique.
|
||||
|
||||
The first form simply takes a coderef that produces the value that should be
|
||||
displayed in the column for any given delta. The arguments passed into the sub
|
||||
are the delta, and the row ID.
|
||||
|
||||
Test2::Compare::Delta->add_column(
|
||||
Foo => sub {
|
||||
my ($delta, $id) = @_;
|
||||
return $delta->... ? 'foo' : 'bar'
|
||||
},
|
||||
);
|
||||
|
||||
The second form allows you some extra options. The C<'value'> key is required,
|
||||
and must be a coderef. All other keys are optional.
|
||||
|
||||
Test2::Compare::Delta->add_column(
|
||||
'Foo', # column name
|
||||
value => sub { ... }, # how to get the cell value
|
||||
alias => 'FOO', # Display name (used in table header)
|
||||
no_collapse => $bool, # Show column even if it has no values?
|
||||
);
|
||||
|
||||
=item $bool = $class->remove_column($NAME)
|
||||
|
||||
This will remove the specified column. This will return true if the column
|
||||
existed and was removed. This will return false if the column did not exist. No
|
||||
exceptions are thrown. If a missing column is a problem then you need to check
|
||||
the return yourself.
|
||||
|
||||
=item $class->set_column_alias($NAME, $ALIAS)
|
||||
|
||||
This can be used to change the table header, overriding the default column
|
||||
names with new ones.
|
||||
|
||||
=back
|
||||
|
||||
=head2 ATTRIBUTES
|
||||
|
||||
=over 4
|
||||
|
||||
=item $bool = $delta->verified
|
||||
|
||||
=item $delta->set_verified($bool)
|
||||
|
||||
This will be true if the delta itself matched, if the delta matched then the
|
||||
problem is in the delta's children, not the delta itself.
|
||||
|
||||
=item $aref = $delta->id
|
||||
|
||||
=item $delta->set_id([$type, $name])
|
||||
|
||||
ID for the delta, used to produce the path into the data structure. An
|
||||
example is C<< ['HASH' => 'foo'] >> which means the delta is in the path
|
||||
C<< ...->{'foo'} >>. Valid types are C<HASH>, C<ARRAY>, C<SCALAR>, C<META>, and
|
||||
C<METHOD>.
|
||||
|
||||
=item $val = $delta->got
|
||||
|
||||
=item $delta->set_got($val)
|
||||
|
||||
Deltas are produced by comparing a received data structure 'got' against a
|
||||
check data structure 'check'. The 'got' attribute contains the value that was
|
||||
received for comparison.
|
||||
|
||||
=item $check = $delta->chk
|
||||
|
||||
=item $check = $delta->check
|
||||
|
||||
=item $delta->set_chk($check)
|
||||
|
||||
=item $delta->set_check($check)
|
||||
|
||||
Deltas are produced by comparing a received data structure 'got' against a
|
||||
check data structure 'check'. The 'check' attribute contains the value that was
|
||||
expected in the comparison.
|
||||
|
||||
C<check> and C<chk> are aliases for the same attribute.
|
||||
|
||||
=item $aref = $delta->children
|
||||
|
||||
=item $delta->set_children([$delta1, $delta2, ...])
|
||||
|
||||
A Delta may have child deltas. If it does then this is an arrayref with those
|
||||
children.
|
||||
|
||||
=item $dne = $delta->dne
|
||||
|
||||
=item $delta->set_dne($dne)
|
||||
|
||||
Sometimes a comparison results in one side or the other not existing at all, in
|
||||
which case this is set to the name of the attribute that does not exist. This
|
||||
can be set to 'got' or 'check'.
|
||||
|
||||
=item $e = $delta->exception
|
||||
|
||||
=item $delta->set_exception($e)
|
||||
|
||||
This will be set to the exception in cases where the comparison failed due to
|
||||
an exception being thrown.
|
||||
|
||||
=back
|
||||
|
||||
=head2 OTHER
|
||||
|
||||
=over 4
|
||||
|
||||
=item $string = $delta->render_got
|
||||
|
||||
Renders the string that should be used in a table to represent the received
|
||||
value in a comparison.
|
||||
|
||||
=item $string = $delta->render_check
|
||||
|
||||
Renders the string that should be used in a table to represent the expected
|
||||
value in a comparison.
|
||||
|
||||
=item $bool = $delta->should_show
|
||||
|
||||
This will return true if the delta should be shown in the table. This is
|
||||
normally true for any unverified delta. This will also be true for deltas that
|
||||
contain extra useful debug information.
|
||||
|
||||
=item $aref = $delta->filter_visible
|
||||
|
||||
This will produce an arrayref of C<< [ $path => $delta ] >> for all deltas that
|
||||
should be displayed in the table.
|
||||
|
||||
=item $aref = $delta->table_header
|
||||
|
||||
This returns an array ref of the headers for the table.
|
||||
|
||||
=item $string = $delta->table_op
|
||||
|
||||
This returns the operator that should be shown in the table.
|
||||
|
||||
=item $string = $delta->table_check_lines
|
||||
|
||||
This returns the defined lines (extra debug info) that should be displayed.
|
||||
|
||||
=item $string = $delta->table_got_lines
|
||||
|
||||
This returns the generated lines (extra debug info) that should be displayed.
|
||||
|
||||
=item $aref = $delta->table_rows
|
||||
|
||||
This returns an arrayref of table rows, each row is itself an arrayref.
|
||||
|
||||
=item @table_lines = $delta->table
|
||||
|
||||
Returns all the lines of the table that should be displayed.
|
||||
|
||||
=back
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Test2-Suite can be found at
|
||||
F<https://github.com/Test-More/Test2-Suite/>.
|
||||
|
||||
=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 2018 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
|
||||
81
database/perl/vendor/lib/Test2/Compare/Event.pm
vendored
Normal file
81
database/perl/vendor/lib/Test2/Compare/Event.pm
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
package Test2::Compare::Event;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Scalar::Util qw/blessed/;
|
||||
|
||||
use Test2::Compare::EventMeta();
|
||||
|
||||
use base 'Test2::Compare::Object';
|
||||
|
||||
our $VERSION = '0.000139';
|
||||
|
||||
use Test2::Util::HashBase qw/etype/;
|
||||
|
||||
sub name {
|
||||
my $self = shift;
|
||||
my $etype = $self->etype;
|
||||
return "<EVENT: $etype>";
|
||||
}
|
||||
|
||||
sub meta_class { 'Test2::Compare::EventMeta' }
|
||||
sub object_base { 'Test2::Event' }
|
||||
|
||||
sub got_lines {
|
||||
my $self = shift;
|
||||
my ($event) = @_;
|
||||
return unless $event;
|
||||
return unless blessed($event);
|
||||
return unless $event->isa('Test2::Event');
|
||||
return unless $event->trace;
|
||||
|
||||
return ($event->trace->line);
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Test2::Compare::Event - Event specific Object subclass.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This module is used to represent an expected event in a deep comparison.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Test2-Suite can be found at
|
||||
F<https://github.com/Test-More/Test2-Suite/>.
|
||||
|
||||
=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 2018 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
|
||||
100
database/perl/vendor/lib/Test2/Compare/EventMeta.pm
vendored
Normal file
100
database/perl/vendor/lib/Test2/Compare/EventMeta.pm
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
package Test2::Compare::EventMeta;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use base 'Test2::Compare::Meta';
|
||||
|
||||
our $VERSION = '0.000139';
|
||||
|
||||
use Test2::Util::HashBase;
|
||||
|
||||
sub get_prop_file { $_[1]->trace->file }
|
||||
sub get_prop_line { $_[1]->trace->line }
|
||||
sub get_prop_package { $_[1]->trace->package }
|
||||
sub get_prop_subname { $_[1]->trace->subname }
|
||||
sub get_prop_debug { $_[1]->trace->debug }
|
||||
sub get_prop_tid { $_[1]->trace->tid }
|
||||
sub get_prop_pid { $_[1]->trace->pid }
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Test2::Compare::EventMeta - Meta class for events in deep comparisons
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This is used in deep comparisons of event objects. You should probably never
|
||||
use this directly.
|
||||
|
||||
=head1 DEFINED CHECKS
|
||||
|
||||
=over 4
|
||||
|
||||
=item file
|
||||
|
||||
File that generated the event.
|
||||
|
||||
=item line
|
||||
|
||||
Line where the event was generated.
|
||||
|
||||
=item package
|
||||
|
||||
Package that generated the event.
|
||||
|
||||
=item subname
|
||||
|
||||
Name of the tool that generated the event.
|
||||
|
||||
=item debug
|
||||
|
||||
The debug information that will be printed in event of a failure.
|
||||
|
||||
=item tid
|
||||
|
||||
Thread ID of the thread that generated the event.
|
||||
|
||||
=item pid
|
||||
|
||||
Process ID of the process that generated the event.
|
||||
|
||||
=back
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Test2-Suite can be found at
|
||||
F<https://github.com/Test-More/Test2-Suite/>.
|
||||
|
||||
=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 2018 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
|
||||
177
database/perl/vendor/lib/Test2/Compare/Float.pm
vendored
Normal file
177
database/perl/vendor/lib/Test2/Compare/Float.pm
vendored
Normal file
@@ -0,0 +1,177 @@
|
||||
package Test2::Compare::Float;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Carp qw/confess/;
|
||||
|
||||
use base 'Test2::Compare::Base';
|
||||
|
||||
our $VERSION = '0.000139';
|
||||
|
||||
our $DEFAULT_TOLERANCE = 1e-08;
|
||||
|
||||
use Test2::Util::HashBase qw/input tolerance precision/;
|
||||
|
||||
# Overloads '!' for us.
|
||||
use Test2::Compare::Negatable;
|
||||
|
||||
sub init {
|
||||
my $self = shift;
|
||||
my $input = $self->{+INPUT};
|
||||
|
||||
if ( exists $self->{+TOLERANCE} and exists $self->{+PRECISION} ) {
|
||||
confess "can't set both tolerance and precision";
|
||||
} elsif (!exists $self->{+PRECISION} and !exists $self->{+TOLERANCE}) {
|
||||
$self->{+TOLERANCE} = $DEFAULT_TOLERANCE
|
||||
}
|
||||
|
||||
confess "input must be defined for 'Float' check"
|
||||
unless defined $input;
|
||||
|
||||
# Check for ''
|
||||
confess "input must be a number for 'Float' check"
|
||||
unless length($input) && $input =~ m/\S/;
|
||||
|
||||
confess "precision must be an integer for 'Float' check"
|
||||
if exists $self->{+PRECISION} && $self->{+PRECISION} !~ m/^\d+$/;
|
||||
|
||||
$self->SUPER::init(@_);
|
||||
}
|
||||
|
||||
sub name {
|
||||
my $self = shift;
|
||||
my $in = $self->{+INPUT};
|
||||
my $precision = $self->{+PRECISION};
|
||||
if ( defined $precision) {
|
||||
return sprintf "%.*f", $precision, $in;
|
||||
}
|
||||
my $tolerance = $self->{+TOLERANCE};
|
||||
return "$in +/- $tolerance";
|
||||
}
|
||||
|
||||
sub operator {
|
||||
my $self = shift;
|
||||
return '' unless @_;
|
||||
my ($got) = @_;
|
||||
|
||||
return '' unless defined($got);
|
||||
return '' unless length($got) && $got =~ m/\S/;
|
||||
|
||||
if ( $self->{+PRECISION} )
|
||||
{
|
||||
return 'ne' if $self->{+NEGATE};
|
||||
return 'eq';
|
||||
}
|
||||
|
||||
return '!=' if $self->{+NEGATE};
|
||||
return '==';
|
||||
}
|
||||
|
||||
sub verify {
|
||||
my $self = shift;
|
||||
my %params = @_;
|
||||
my ($got, $exists) = @params{qw/got exists/};
|
||||
|
||||
return 0 unless $exists;
|
||||
return 0 unless defined $got;
|
||||
return 0 if ref $got;
|
||||
return 0 unless length($got) && $got =~ m/\S/;
|
||||
|
||||
my $input = $self->{+INPUT};
|
||||
my $negate = $self->{+NEGATE};
|
||||
my $tolerance = $self->{+TOLERANCE};
|
||||
my $precision = $self->{+PRECISION};
|
||||
|
||||
my @warnings;
|
||||
my $out;
|
||||
{
|
||||
local $SIG{__WARN__} = sub { push @warnings => @_ };
|
||||
|
||||
my $equal = ($input == $got);
|
||||
if (!$equal) {
|
||||
if (defined $tolerance) {
|
||||
$equal = 1 if
|
||||
$got > $input - $tolerance &&
|
||||
$got < $input + $tolerance;
|
||||
} else {
|
||||
$equal =
|
||||
sprintf("%.*f", $precision, $got) eq
|
||||
sprintf("%.*f", $precision, $input);
|
||||
}
|
||||
}
|
||||
|
||||
$out = $negate ? !$equal : $equal;
|
||||
}
|
||||
|
||||
for my $warn (@warnings) {
|
||||
if ($warn =~ m/numeric/) {
|
||||
$out = 0;
|
||||
next; # This warning won't help anyone.
|
||||
}
|
||||
warn $warn;
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Test2::Compare::Float - Compare two values as numbers with tolerance.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This is used to compare two numbers. You can also check that two numbers are not
|
||||
the same.
|
||||
|
||||
This is similar to Test2::Compare::Number, with extra checks to work around floating
|
||||
point representation issues.
|
||||
|
||||
The optional 'tolerance' parameter controls how close the two numbers must be to
|
||||
be considered equal. Tolerance defaults to 1e-08.
|
||||
|
||||
B<Note>: This will fail if the received value is undefined. It must be a number.
|
||||
|
||||
B<Note>: This will fail if the comparison generates a non-numeric value warning
|
||||
(which will not be shown). This is because it must get a number. The warning is
|
||||
not shown as it will report to a useless line and filename. However, the test
|
||||
diagnostics show both values.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Test2-Suite can be found at
|
||||
F<https://github.com/Test-More/Test2-Suite/>.
|
||||
|
||||
=head1 MAINTAINERS
|
||||
|
||||
=over 4
|
||||
|
||||
=item Chad Granum E<lt>exodist@cpan.orgE<gt>
|
||||
|
||||
=back
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
=over 4
|
||||
|
||||
=item Andrew Grangaard E<lt>spazm@cpan.orgE<gt>
|
||||
|
||||
=back
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright 2018 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
|
||||
238
database/perl/vendor/lib/Test2/Compare/Hash.pm
vendored
Normal file
238
database/perl/vendor/lib/Test2/Compare/Hash.pm
vendored
Normal file
@@ -0,0 +1,238 @@
|
||||
package Test2::Compare::Hash;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use base 'Test2::Compare::Base';
|
||||
|
||||
our $VERSION = '0.000139';
|
||||
|
||||
use Test2::Util::HashBase qw/inref meta ending items order for_each_key for_each_val/;
|
||||
|
||||
use Carp qw/croak confess/;
|
||||
use Scalar::Util qw/reftype/;
|
||||
|
||||
sub init {
|
||||
my $self = shift;
|
||||
|
||||
if( defined( my $ref = $self->{+INREF} ) ) {
|
||||
croak "Cannot specify both 'inref' and 'items'" if $self->{+ITEMS};
|
||||
croak "Cannot specify both 'inref' and 'order'" if $self->{+ORDER};
|
||||
$self->{+ITEMS} = {%$ref};
|
||||
$self->{+ORDER} = [sort keys %$ref];
|
||||
}
|
||||
else {
|
||||
# Clone the ref to be safe
|
||||
$self->{+ITEMS} = $self->{+ITEMS} ? {%{$self->{+ITEMS}}} : {};
|
||||
if ($self->{+ORDER}) {
|
||||
my @all = keys %{$self->{+ITEMS}};
|
||||
my %have = map { $_ => 1 } @{$self->{+ORDER}};
|
||||
my @missing = grep { !$have{$_} } @all;
|
||||
croak "Keys are missing from the 'order' array: " . join(', ', sort @missing)
|
||||
if @missing;
|
||||
}
|
||||
else {
|
||||
$self->{+ORDER} = [sort keys %{$self->{+ITEMS}}];
|
||||
}
|
||||
}
|
||||
|
||||
$self->{+FOR_EACH_KEY} ||= [];
|
||||
$self->{+FOR_EACH_VAL} ||= [];
|
||||
|
||||
$self->SUPER::init();
|
||||
}
|
||||
|
||||
sub name { '<HASH>' }
|
||||
|
||||
sub meta_class { 'Test2::Compare::Meta' }
|
||||
|
||||
sub verify {
|
||||
my $self = shift;
|
||||
my %params = @_;
|
||||
my ($got, $exists) = @params{qw/got exists/};
|
||||
|
||||
return 0 unless $exists;
|
||||
return 0 unless defined $got;
|
||||
return 0 unless ref($got);
|
||||
return 0 unless reftype($got) eq 'HASH';
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub add_prop {
|
||||
my $self = shift;
|
||||
$self->{+META} = $self->meta_class->new unless defined $self->{+META};
|
||||
$self->{+META}->add_prop(@_);
|
||||
}
|
||||
|
||||
sub add_field {
|
||||
my $self = shift;
|
||||
my ($name, $check) = @_;
|
||||
|
||||
croak "field name is required"
|
||||
unless defined $name;
|
||||
|
||||
croak "field '$name' has already been specified"
|
||||
if exists $self->{+ITEMS}->{$name};
|
||||
|
||||
push @{$self->{+ORDER}} => $name;
|
||||
$self->{+ITEMS}->{$name} = $check;
|
||||
}
|
||||
|
||||
sub add_for_each_key {
|
||||
my $self = shift;
|
||||
push @{$self->{+FOR_EACH_KEY}} => @_;
|
||||
}
|
||||
|
||||
sub add_for_each_val {
|
||||
my $self = shift;
|
||||
push @{$self->{+FOR_EACH_VAL}} => @_;
|
||||
}
|
||||
|
||||
sub deltas {
|
||||
my $self = shift;
|
||||
my %params = @_;
|
||||
my ($got, $convert, $seen) = @params{qw/got convert seen/};
|
||||
|
||||
my @deltas;
|
||||
my $items = $self->{+ITEMS};
|
||||
my $each_key = $self->{+FOR_EACH_KEY};
|
||||
my $each_val = $self->{+FOR_EACH_VAL};
|
||||
|
||||
# Make a copy that we can munge as needed.
|
||||
my %fields = %$got;
|
||||
|
||||
my $meta = $self->{+META};
|
||||
push @deltas => $meta->deltas(%params) if defined $meta;
|
||||
|
||||
for my $key (@{$self->{+ORDER}}) {
|
||||
my $check = $convert->($items->{$key});
|
||||
my $exists = exists $fields{$key};
|
||||
my $val = delete $fields{$key};
|
||||
|
||||
if ($exists) {
|
||||
for my $kcheck (@$each_key) {
|
||||
$kcheck = $convert->($kcheck);
|
||||
|
||||
push @deltas => $kcheck->run(
|
||||
id => [HASHKEY => $key],
|
||||
convert => $convert,
|
||||
seen => $seen,
|
||||
exists => $exists,
|
||||
got => $key,
|
||||
);
|
||||
}
|
||||
|
||||
for my $vcheck (@$each_val) {
|
||||
$vcheck = $convert->($vcheck);
|
||||
|
||||
push @deltas => $vcheck->run(
|
||||
id => [HASH => $key],
|
||||
convert => $convert,
|
||||
seen => $seen,
|
||||
exists => $exists,
|
||||
got => $val,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
push @deltas => $check->run(
|
||||
id => [HASH => $key],
|
||||
convert => $convert,
|
||||
seen => $seen,
|
||||
exists => $exists,
|
||||
$exists ? (got => $val) : (),
|
||||
);
|
||||
}
|
||||
|
||||
if (keys %fields) {
|
||||
for my $key (sort keys %fields) {
|
||||
my $val = $fields{$key};
|
||||
|
||||
for my $kcheck (@$each_key) {
|
||||
$kcheck = $convert->($kcheck);
|
||||
|
||||
push @deltas => $kcheck->run(
|
||||
id => [HASHKEY => $key],
|
||||
convert => $convert,
|
||||
seen => $seen,
|
||||
got => $key,
|
||||
exists => 1,
|
||||
);
|
||||
}
|
||||
|
||||
for my $vcheck (@$each_val) {
|
||||
$vcheck = $convert->($vcheck);
|
||||
|
||||
push @deltas => $vcheck->run(
|
||||
id => [HASH => $key],
|
||||
convert => $convert,
|
||||
seen => $seen,
|
||||
got => $val,
|
||||
exists => 1,
|
||||
);
|
||||
}
|
||||
|
||||
# if items are left over, and ending is true, we have a problem!
|
||||
if ($self->{+ENDING}) {
|
||||
push @deltas => $self->delta_class->new(
|
||||
dne => 'check',
|
||||
verified => undef,
|
||||
id => [HASH => $key],
|
||||
got => $val,
|
||||
check => undef,
|
||||
|
||||
$self->{+ENDING} eq 'implicit' ? (note => 'implicit end') : (),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return @deltas;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Test2::Compare::Hash - Representation of a hash in a deep comparison.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
In deep comparisons this class is used to represent a hash.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Test2-Suite can be found at
|
||||
F<https://github.com/Test-More/Test2-Suite/>.
|
||||
|
||||
=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 2018 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
|
||||
100
database/perl/vendor/lib/Test2/Compare/Isa.pm
vendored
Normal file
100
database/perl/vendor/lib/Test2/Compare/Isa.pm
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
package Test2::Compare::Isa;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Carp qw/confess/;
|
||||
use Scalar::Util qw/blessed/;
|
||||
|
||||
use base 'Test2::Compare::Base';
|
||||
|
||||
our $VERSION = '0.000139';
|
||||
|
||||
use Test2::Util::HashBase qw/input/;
|
||||
|
||||
# Overloads '!' for us.
|
||||
use Test2::Compare::Negatable;
|
||||
|
||||
sub init {
|
||||
my $self = shift;
|
||||
confess "input must be defined for 'Isa' check"
|
||||
unless defined $self->{+INPUT};
|
||||
|
||||
$self->SUPER::init(@_);
|
||||
}
|
||||
|
||||
sub name {
|
||||
my $self = shift;
|
||||
my $in = $self->{+INPUT};
|
||||
return "$in";
|
||||
}
|
||||
|
||||
sub operator {
|
||||
my $self = shift;
|
||||
return '!isa' if $self->{+NEGATE};
|
||||
return 'isa';
|
||||
}
|
||||
|
||||
sub verify {
|
||||
my $self = shift;
|
||||
my %params = @_;
|
||||
my ($got, $exists) = @params{qw/got exists/};
|
||||
|
||||
return 0 unless $exists;
|
||||
|
||||
my $input = $self->{+INPUT};
|
||||
my $negate = $self->{+NEGATE};
|
||||
my $isa = blessed($got) && $got->isa($input);
|
||||
|
||||
return !$isa if $negate;
|
||||
return $isa;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Test2::Compare::Isa - Check if the value is an instance of the class.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This is used to check if the got value is an instance of the expected class.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Test2-Suite can be found at
|
||||
F<https://github.com/Test-More/Test2-Suite/>.
|
||||
|
||||
=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>
|
||||
|
||||
=item TOYAMA Nao E<lt>nanto@moon.email.ne.jpE<gt>
|
||||
|
||||
=back
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright 2018 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
|
||||
183
database/perl/vendor/lib/Test2/Compare/Meta.pm
vendored
Normal file
183
database/perl/vendor/lib/Test2/Compare/Meta.pm
vendored
Normal file
@@ -0,0 +1,183 @@
|
||||
package Test2::Compare::Meta;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Test2::Compare::Delta();
|
||||
use Test2::Compare::Isa();
|
||||
|
||||
use base 'Test2::Compare::Base';
|
||||
|
||||
our $VERSION = '0.000139';
|
||||
|
||||
use Test2::Util::HashBase qw/items/;
|
||||
|
||||
use Carp qw/croak confess/;
|
||||
use Scalar::Util qw/reftype blessed/;
|
||||
|
||||
sub init {
|
||||
my $self = shift;
|
||||
$self->{+ITEMS} ||= [];
|
||||
$self->SUPER::init();
|
||||
}
|
||||
|
||||
sub name { '<META CHECKS>' }
|
||||
|
||||
sub verify {
|
||||
my $self = shift;
|
||||
my %params = @_;
|
||||
return $params{exists} ? 1 : 0;
|
||||
}
|
||||
|
||||
sub add_prop {
|
||||
my $self = shift;
|
||||
my ($name, $check) = @_;
|
||||
|
||||
croak "prop name is required"
|
||||
unless defined $name;
|
||||
|
||||
croak "check is required"
|
||||
unless defined $check;
|
||||
|
||||
my $meth = "get_prop_$name";
|
||||
croak "'$name' is not a known property"
|
||||
unless $self->can($meth);
|
||||
|
||||
if ($name eq 'isa') {
|
||||
if (blessed($check) && $check->isa('Test2::Compare::Wildcard')) {
|
||||
# Carry forward file and lines that are set in Test2::Tools::Compare::prop.
|
||||
$check = Test2::Compare::Isa->new(
|
||||
input => $check->expect,
|
||||
file => $check->file,
|
||||
lines => $check->lines,
|
||||
);
|
||||
} else {
|
||||
$check = Test2::Compare::Isa->new(input => $check);
|
||||
}
|
||||
}
|
||||
|
||||
push @{$self->{+ITEMS}} => [$meth, $check, $name];
|
||||
}
|
||||
|
||||
sub deltas {
|
||||
my $self = shift;
|
||||
my %params = @_;
|
||||
my ($got, $convert, $seen) = @params{qw/got convert seen/};
|
||||
|
||||
my @deltas;
|
||||
my $items = $self->{+ITEMS};
|
||||
|
||||
for my $set (@$items) {
|
||||
my ($meth, $check, $name) = @$set;
|
||||
|
||||
$check = $convert->($check);
|
||||
|
||||
my $val = $self->$meth($got);
|
||||
|
||||
push @deltas => $check->run(
|
||||
id => [META => $name],
|
||||
got => $val,
|
||||
convert => $convert,
|
||||
seen => $seen,
|
||||
);
|
||||
}
|
||||
|
||||
return @deltas;
|
||||
}
|
||||
|
||||
sub get_prop_blessed { blessed($_[1]) }
|
||||
|
||||
sub get_prop_reftype { reftype($_[1]) }
|
||||
|
||||
sub get_prop_isa { $_[1] }
|
||||
|
||||
sub get_prop_this { $_[1] }
|
||||
|
||||
sub get_prop_size {
|
||||
my $self = shift;
|
||||
my ($it) = @_;
|
||||
|
||||
my $type = reftype($it) || '';
|
||||
|
||||
return scalar @$it if $type eq 'ARRAY';
|
||||
return scalar keys %$it if $type eq 'HASH';
|
||||
return undef;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Test2::Compare::Meta - Check library for meta-checks
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Sometimes in a deep comparison you want to run extra checks against an item
|
||||
down the chain. This library allows you to write a check that verifies several
|
||||
attributes of an item.
|
||||
|
||||
=head1 DEFINED CHECKS
|
||||
|
||||
=over 4
|
||||
|
||||
=item blessed
|
||||
|
||||
Lets you check that an item is blessed, and that it is blessed into the
|
||||
expected class.
|
||||
|
||||
=item reftype
|
||||
|
||||
Lets you check the reftype of the item.
|
||||
|
||||
=item isa
|
||||
|
||||
Lets you check if the item is an instance of the expected class.
|
||||
|
||||
=item this
|
||||
|
||||
Lets you check the item itself.
|
||||
|
||||
=item size
|
||||
|
||||
Lets you check the size of the item. For an arrayref this is the number of
|
||||
elements. For a hashref this is the number of keys. For everything else this is
|
||||
undef.
|
||||
|
||||
=back
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Test2-Suite can be found at
|
||||
F<https://github.com/Test-More/Test2-Suite/>.
|
||||
|
||||
=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 2018 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
|
||||
121
database/perl/vendor/lib/Test2/Compare/Negatable.pm
vendored
Normal file
121
database/perl/vendor/lib/Test2/Compare/Negatable.pm
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
package Test2::Compare::Negatable;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
our $VERSION = '0.000139';
|
||||
|
||||
require overload;
|
||||
require Test2::Util::HashBase;
|
||||
|
||||
sub import {
|
||||
my ($pkg, $file, $line) = caller;
|
||||
|
||||
my $sub = eval <<" EOT" or die $@;
|
||||
package $pkg;
|
||||
#line $line "$file"
|
||||
sub { overload->import('!' => 'clone_negate', fallback => 1); Test2::Util::HashBase->import('negate')}
|
||||
EOT
|
||||
|
||||
$sub->();
|
||||
|
||||
no strict 'refs';
|
||||
*{"$pkg\::clone_negate"} = \&clone_negate;
|
||||
*{"$pkg\::toggle_negate"} = \&toggle_negate;
|
||||
}
|
||||
|
||||
sub clone_negate {
|
||||
my $self = shift;
|
||||
my $clone = $self->clone;
|
||||
$clone->toggle_negate;
|
||||
return $clone;
|
||||
}
|
||||
|
||||
sub toggle_negate {
|
||||
my $self = shift;
|
||||
$self->set_negate($self->negate ? 0 : 1);
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Test2::Compare::Negatable - Poor mans 'role' for compare objects that can be negated.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Using this package inside an L<Test2::Compare::Base> subclass will overload
|
||||
C<!$obj> and import C<clone_negate()> and C<toggle_negate()>.
|
||||
|
||||
=head1 WHY?
|
||||
|
||||
Until perl 5.18 the 'fallback' parameter to L<overload> would not be inherited,
|
||||
so we cannot use inheritance for the behavior we actually want. This module
|
||||
works around the problem by emulating the C<use overload> call we want for each
|
||||
consumer class.
|
||||
|
||||
=head1 ATTRIBUTES
|
||||
|
||||
=over 4
|
||||
|
||||
=item $bool = $obj->negate
|
||||
|
||||
=item $obj->set_negate($bool)
|
||||
|
||||
=item $attr = NEGATE()
|
||||
|
||||
The NEGATE attribute will be added via L<Test2::Util::HashBase>.
|
||||
|
||||
=back
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=over 4
|
||||
|
||||
=item $clone = $obj->clone_negate()
|
||||
|
||||
Create a shallow copy of the object, and call C<toggle_negate> on it.
|
||||
|
||||
=item $obj->toggle_negate()
|
||||
|
||||
Toggle the negate attribute. If the attribute was on it will now be off, if it
|
||||
was off it will now be on.
|
||||
|
||||
=back
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Test2-Suite can be found at
|
||||
F<https://github.com/Test-More/Test2-Suite/>.
|
||||
|
||||
=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 2018 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
|
||||
133
database/perl/vendor/lib/Test2/Compare/Number.pm
vendored
Normal file
133
database/perl/vendor/lib/Test2/Compare/Number.pm
vendored
Normal file
@@ -0,0 +1,133 @@
|
||||
package Test2::Compare::Number;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Carp qw/confess/;
|
||||
|
||||
use base 'Test2::Compare::Base';
|
||||
|
||||
our $VERSION = '0.000139';
|
||||
|
||||
use Test2::Util::HashBase qw/input/;
|
||||
|
||||
# Overloads '!' for us.
|
||||
use Test2::Compare::Negatable;
|
||||
|
||||
sub init {
|
||||
my $self = shift;
|
||||
my $input = $self->{+INPUT};
|
||||
|
||||
confess "input must be defined for 'Number' check"
|
||||
unless defined $input;
|
||||
|
||||
# Check for ''
|
||||
confess "input must be a number for 'Number' check"
|
||||
unless length($input) && $input =~ m/\S/;
|
||||
|
||||
$self->SUPER::init(@_);
|
||||
}
|
||||
|
||||
sub name {
|
||||
my $self = shift;
|
||||
my $in = $self->{+INPUT};
|
||||
return $in;
|
||||
}
|
||||
|
||||
sub operator {
|
||||
my $self = shift;
|
||||
return '' unless @_;
|
||||
my ($got) = @_;
|
||||
|
||||
return '' unless defined($got);
|
||||
return '' unless length($got) && $got =~ m/\S/;
|
||||
|
||||
return '!=' if $self->{+NEGATE};
|
||||
return '==';
|
||||
}
|
||||
|
||||
sub verify {
|
||||
my $self = shift;
|
||||
my %params = @_;
|
||||
my ($got, $exists) = @params{qw/got exists/};
|
||||
|
||||
return 0 unless $exists;
|
||||
return 0 unless defined $got;
|
||||
return 0 if ref $got;
|
||||
return 0 unless length($got) && $got =~ m/\S/;
|
||||
|
||||
my $input = $self->{+INPUT};
|
||||
my $negate = $self->{+NEGATE};
|
||||
|
||||
my @warnings;
|
||||
my $out;
|
||||
{
|
||||
local $SIG{__WARN__} = sub { push @warnings => @_ };
|
||||
$out = $negate ? ($input != $got) : ($input == $got);
|
||||
}
|
||||
|
||||
for my $warn (@warnings) {
|
||||
if ($warn =~ m/numeric/) {
|
||||
$out = 0;
|
||||
next; # This warning won't help anyone.
|
||||
}
|
||||
warn $warn;
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Test2::Compare::Number - Compare two values as numbers
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This is used to compare two numbers. You can also check that two numbers are not
|
||||
the same.
|
||||
|
||||
B<Note>: This will fail if the received value is undefined. It must be a number.
|
||||
|
||||
B<Note>: This will fail if the comparison generates a non-numeric value warning
|
||||
(which will not be shown). This is because it must get a number. The warning is
|
||||
not shown as it will report to a useless line and filename. However, the test
|
||||
diagnostics show both values.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Test2-Suite can be found at
|
||||
F<https://github.com/Test-More/Test2-Suite/>.
|
||||
|
||||
=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 2018 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
|
||||
256
database/perl/vendor/lib/Test2/Compare/Object.pm
vendored
Normal file
256
database/perl/vendor/lib/Test2/Compare/Object.pm
vendored
Normal file
@@ -0,0 +1,256 @@
|
||||
package Test2::Compare::Object;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Test2::Util qw/try/;
|
||||
|
||||
use Test2::Compare::Meta();
|
||||
|
||||
use base 'Test2::Compare::Base';
|
||||
|
||||
our $VERSION = '0.000139';
|
||||
|
||||
use Test2::Util::HashBase qw/calls meta refcheck ending/;
|
||||
|
||||
use Carp qw/croak confess/;
|
||||
use Scalar::Util qw/reftype blessed/;
|
||||
|
||||
sub init {
|
||||
my $self = shift;
|
||||
$self->{+CALLS} ||= [];
|
||||
$self->SUPER::init();
|
||||
}
|
||||
|
||||
sub name { '<OBJECT>' }
|
||||
|
||||
sub meta_class { 'Test2::Compare::Meta' }
|
||||
sub object_base { 'UNIVERSAL' }
|
||||
|
||||
sub verify {
|
||||
my $self = shift;
|
||||
my %params = @_;
|
||||
my ($got, $exists) = @params{qw/got exists/};
|
||||
|
||||
return 0 unless $exists;
|
||||
return 0 unless defined $got;
|
||||
return 0 unless ref($got);
|
||||
return 0 unless blessed($got);
|
||||
return 0 unless $got->isa($self->object_base);
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub add_prop {
|
||||
my $self = shift;
|
||||
$self->{+META} = $self->meta_class->new unless defined $self->{+META};
|
||||
$self->{+META}->add_prop(@_);
|
||||
}
|
||||
|
||||
sub add_field {
|
||||
my $self = shift;
|
||||
$self->{+REFCHECK} = Test2::Compare::Hash->new unless defined $self->{+REFCHECK};
|
||||
|
||||
croak "Underlying reference does not have fields"
|
||||
unless $self->{+REFCHECK}->can('add_field');
|
||||
|
||||
$self->{+REFCHECK}->add_field(@_);
|
||||
}
|
||||
|
||||
sub add_item {
|
||||
my $self = shift;
|
||||
$self->{+REFCHECK} = Test2::Compare::Array->new unless defined $self->{+REFCHECK};
|
||||
|
||||
croak "Underlying reference does not have items"
|
||||
unless $self->{+REFCHECK}->can('add_item');
|
||||
|
||||
$self->{+REFCHECK}->add_item(@_);
|
||||
}
|
||||
|
||||
sub add_call {
|
||||
my $self = shift;
|
||||
my ($meth, $check, $name, $context) = @_;
|
||||
$name ||= ref $meth eq 'ARRAY' ? $meth->[0]
|
||||
: ref $meth eq 'CODE' ? '\&CODE'
|
||||
: $meth;
|
||||
push @{$self->{+CALLS}} => [$meth, $check, $name, $context || 'scalar'];
|
||||
}
|
||||
|
||||
sub deltas {
|
||||
my $self = shift;
|
||||
my %params = @_;
|
||||
my ($got, $convert, $seen) = @params{qw/got convert seen/};
|
||||
|
||||
my @deltas;
|
||||
my $meta = $self->{+META};
|
||||
my $refcheck = $self->{+REFCHECK};
|
||||
|
||||
push @deltas => $meta->deltas(%params) if defined $meta;
|
||||
|
||||
for my $call (@{$self->{+CALLS}}) {
|
||||
my ($meth, $check, $name, $context)= @$call;
|
||||
$context ||= 'scalar';
|
||||
|
||||
$check = $convert->($check);
|
||||
|
||||
my @args;
|
||||
if (ref($meth) eq 'ARRAY') {
|
||||
($meth,@args) = @{$meth};
|
||||
}
|
||||
|
||||
my $exists = ref($meth) || $got->can($meth);
|
||||
my $val;
|
||||
my ($ok, $err) = try {
|
||||
$val = $exists
|
||||
? ( $context eq 'list' ? [ $got->$meth(@args) ] :
|
||||
$context eq 'hash' ? { $got->$meth(@args) } :
|
||||
$got->$meth(@args)
|
||||
)
|
||||
: undef;
|
||||
};
|
||||
|
||||
if (!$ok) {
|
||||
push @deltas => $self->delta_class->new(
|
||||
verified => undef,
|
||||
id => [METHOD => $name],
|
||||
got => undef,
|
||||
check => $check,
|
||||
exception => $err,
|
||||
);
|
||||
}
|
||||
else {
|
||||
push @deltas => $check->run(
|
||||
id => [METHOD => $name],
|
||||
convert => $convert,
|
||||
seen => $seen,
|
||||
exists => $exists,
|
||||
$exists ? (got => $val) : (),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return @deltas unless defined $refcheck;
|
||||
|
||||
$refcheck->set_ending($self->{+ENDING});
|
||||
|
||||
if ($refcheck->verify(%params)) {
|
||||
push @deltas => $refcheck->deltas(%params);
|
||||
}
|
||||
else {
|
||||
push @deltas => $self->delta_class->new(
|
||||
verified => undef,
|
||||
id => [META => 'Object Ref'],
|
||||
got => $got,
|
||||
check => $refcheck,
|
||||
);
|
||||
}
|
||||
|
||||
return @deltas;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Test2::Compare::Object - Representation of an object during deep
|
||||
comparison.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This class lets you specify an expected object in a deep comparison. You can
|
||||
check the fields/elements of the underlying reference, call methods to verify
|
||||
results, and do meta checks for object type and ref type.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=over 4
|
||||
|
||||
=item $class = $obj->meta_class
|
||||
|
||||
The meta-class to be used when checking the object type. This is mainly listed
|
||||
because it is useful to override for specialized object subclasses.
|
||||
|
||||
This normally just returns L<Test2::Compare::Meta>.
|
||||
|
||||
=item $class = $obj->object_base
|
||||
|
||||
The base-class to be expected when checking the object type. This is mainly
|
||||
listed because it is useful to override for specialized object subclasses.
|
||||
|
||||
This normally just returns 'UNIVERSAL'.
|
||||
|
||||
=item $obj->add_prop(...)
|
||||
|
||||
Add a meta-property to check, see L<Test2::Compare::Meta>. This method
|
||||
just delegates.
|
||||
|
||||
=item $obj->add_field(...)
|
||||
|
||||
Add a hash-field to check, see L<Test2::Compare::Hash>. This method
|
||||
just delegates.
|
||||
|
||||
=item $obj->add_item(...)
|
||||
|
||||
Add an array item to check, see L<Test2::Compare::Array>. This method
|
||||
just delegates.
|
||||
|
||||
=item $obj->add_call($method, $check)
|
||||
|
||||
=item $obj->add_call($method, $check, $name)
|
||||
|
||||
=item $obj->add_call($method, $check, $name, $context)
|
||||
|
||||
Add a method call check. This will call the specified method on your object and
|
||||
verify the result. C<$method> may be a method name, an array ref, or a coderef.
|
||||
|
||||
If it's an arrayref, the first element must be the method name, and
|
||||
the rest are arguments that will be passed to it.
|
||||
|
||||
In the case of a coderef it can be helpful to provide an alternate
|
||||
name. When no name is provided the name is either C<$method> or the
|
||||
string '\&CODE'.
|
||||
|
||||
If C<$context> is C<'list'>, the method will be invoked in list
|
||||
context, and the result will be an arrayref.
|
||||
|
||||
If C<$context> is C<'hash'>, the method will be invoked in list
|
||||
context, and the result will be a hashref (this will warn if the
|
||||
method returns an odd number of values).
|
||||
|
||||
=back
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Test2-Suite can be found at
|
||||
F<https://github.com/Test-More/Test2-Suite/>.
|
||||
|
||||
=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 2018 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
|
||||
175
database/perl/vendor/lib/Test2/Compare/OrderedSubset.pm
vendored
Normal file
175
database/perl/vendor/lib/Test2/Compare/OrderedSubset.pm
vendored
Normal file
@@ -0,0 +1,175 @@
|
||||
package Test2::Compare::OrderedSubset;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use base 'Test2::Compare::Base';
|
||||
|
||||
our $VERSION = '0.000139';
|
||||
|
||||
use Test2::Util::HashBase qw/inref items/;
|
||||
|
||||
use Carp qw/croak/;
|
||||
use Scalar::Util qw/reftype/;
|
||||
|
||||
sub init {
|
||||
my $self = shift;
|
||||
|
||||
if(my $ref = $self->{+INREF}) {
|
||||
croak "Cannot specify both 'inref' and 'items'" if $self->{+ITEMS};
|
||||
croak "'inref' must be an array reference, got '$ref'" unless reftype($ref) eq 'ARRAY';
|
||||
$self->{+ITEMS} = [@{$self->{+INREF}}];
|
||||
}
|
||||
|
||||
$self->{+ITEMS} ||= [];
|
||||
|
||||
$self->SUPER::init();
|
||||
}
|
||||
|
||||
sub name { '<ORDERED SUBSET>' }
|
||||
|
||||
sub verify {
|
||||
my $self = shift;
|
||||
my %params = @_;
|
||||
|
||||
return 0 unless $params{exists};
|
||||
defined( my $got = $params{got} ) || return 0;
|
||||
return 0 unless ref($got);
|
||||
return 0 unless reftype($got) eq 'ARRAY';
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub add_item {
|
||||
my $self = shift;
|
||||
my $check = pop;
|
||||
|
||||
push @{$self->{+ITEMS}} => $check;
|
||||
}
|
||||
|
||||
sub deltas {
|
||||
my $self = shift;
|
||||
my %params = @_;
|
||||
my ($got, $convert, $seen) = @params{qw/got convert seen/};
|
||||
|
||||
my @deltas;
|
||||
my $state = 0;
|
||||
my $items = $self->{+ITEMS};
|
||||
|
||||
my $idx = 0;
|
||||
|
||||
for my $item (@$items) {
|
||||
my $check = $convert->($item);
|
||||
|
||||
my $i = $idx;
|
||||
my $found;
|
||||
while($i < @$got) {
|
||||
my $val = $got->[$i++];
|
||||
next if $check->run(
|
||||
id => [ARRAY => $i],
|
||||
convert => $convert,
|
||||
seen => $seen,
|
||||
exists => 1,
|
||||
got => $val,
|
||||
);
|
||||
|
||||
$idx = $i;
|
||||
$found++;
|
||||
last;
|
||||
}
|
||||
|
||||
next if $found;
|
||||
|
||||
push @deltas => Test2::Compare::Delta->new(
|
||||
verified => 0,
|
||||
id => ['ARRAY', '?'],
|
||||
check => $check,
|
||||
dne => 'got',
|
||||
);
|
||||
}
|
||||
|
||||
return @deltas;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Test2::Compare::OrderedSubset - Internal representation of an ordered subset.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This module is used to ensure an array has all the expected items int he
|
||||
expected order. It ignores any unexpected items mixed into the array. It only
|
||||
cares that all the expected values are present, and in order, everything else
|
||||
is noise.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=over 4
|
||||
|
||||
=item $ref = $arr->inref()
|
||||
|
||||
If the instance was constructed from an actual array, this will have the
|
||||
reference to that array.
|
||||
|
||||
=item $arrayref = $arr->items()
|
||||
|
||||
=item $arr->set_items($arrayref)
|
||||
|
||||
All the expected items, in order.
|
||||
|
||||
=item $name = $arr->name()
|
||||
|
||||
Always returns the string C<< "<ORDERED SUBSET>" >>.
|
||||
|
||||
=item $bool = $arr->verify(got => $got, exists => $bool)
|
||||
|
||||
Check if C<$got> is an array reference or not.
|
||||
|
||||
=item $arr->add_item($item)
|
||||
|
||||
Add an item to the list of values to check.
|
||||
|
||||
=item @deltas = $arr->deltas(got => $got, convert => \&convert, seen => \%seen)
|
||||
|
||||
Find the differences between the expected array values and those in the C<$got>
|
||||
arrayref.
|
||||
|
||||
=back
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Test2-Suite can be found at
|
||||
F<https://github.com/Test-More/Test2-Suite/>.
|
||||
|
||||
=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 2018 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
|
||||
93
database/perl/vendor/lib/Test2/Compare/Pattern.pm
vendored
Normal file
93
database/perl/vendor/lib/Test2/Compare/Pattern.pm
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
package Test2::Compare::Pattern;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use base 'Test2::Compare::Base';
|
||||
|
||||
our $VERSION = '0.000139';
|
||||
|
||||
use Test2::Util::HashBase qw/pattern stringify_got/;
|
||||
|
||||
# Overloads '!' for us.
|
||||
use Test2::Compare::Negatable;
|
||||
|
||||
use Carp qw/croak/;
|
||||
|
||||
sub init {
|
||||
my $self = shift;
|
||||
|
||||
croak "'pattern' is a required attribute" unless $self->{+PATTERN};
|
||||
|
||||
$self->{+STRINGIFY_GOT} ||= 0;
|
||||
|
||||
$self->SUPER::init();
|
||||
}
|
||||
|
||||
sub name { shift->{+PATTERN} . "" }
|
||||
sub operator { shift->{+NEGATE} ? '!~' : '=~' }
|
||||
|
||||
sub verify {
|
||||
my $self = shift;
|
||||
my %params = @_;
|
||||
my ($got, $exists) = @params{qw/got exists/};
|
||||
|
||||
return 0 unless $exists;
|
||||
return 0 unless defined($got);
|
||||
return 0 if ref $got && !$self->stringify_got;
|
||||
|
||||
return $got !~ $self->{+PATTERN}
|
||||
if $self->{+NEGATE};
|
||||
|
||||
return $got =~ $self->{+PATTERN};
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Test2::Compare::Pattern - Use a pattern to validate values in a deep
|
||||
comparison.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This allows you to use a regex to validate a value in a deep comparison.
|
||||
Sometimes a value just needs to look right, it may not need to be exact. An
|
||||
example is a memory address that might change from run to run.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Test2-Suite can be found at
|
||||
F<https://github.com/Test-More/Test2-Suite/>.
|
||||
|
||||
=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 2018 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
|
||||
109
database/perl/vendor/lib/Test2/Compare/Ref.pm
vendored
Normal file
109
database/perl/vendor/lib/Test2/Compare/Ref.pm
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
package Test2::Compare::Ref;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use base 'Test2::Compare::Base';
|
||||
|
||||
our $VERSION = '0.000139';
|
||||
|
||||
use Test2::Util::HashBase qw/input/;
|
||||
|
||||
use Test2::Util::Ref qw/render_ref rtype/;
|
||||
use Scalar::Util qw/refaddr/;
|
||||
use Carp qw/croak/;
|
||||
|
||||
sub init {
|
||||
my $self = shift;
|
||||
|
||||
croak "'input' is a required attribute"
|
||||
unless $self->{+INPUT};
|
||||
|
||||
croak "'input' must be a reference, got '" . $self->{+INPUT} . "'"
|
||||
unless ref $self->{+INPUT};
|
||||
|
||||
$self->SUPER::init();
|
||||
}
|
||||
|
||||
sub operator { '==' }
|
||||
|
||||
sub name { render_ref($_[0]->{+INPUT}) }
|
||||
|
||||
sub verify {
|
||||
my $self = shift;
|
||||
my %params = @_;
|
||||
my ($got, $exists) = @params{qw/got exists/};
|
||||
|
||||
return 0 unless $exists;
|
||||
|
||||
my $in = $self->{+INPUT};
|
||||
return 0 unless ref $in;
|
||||
return 0 unless ref $got;
|
||||
|
||||
my $in_type = rtype($in);
|
||||
my $got_type = rtype($got);
|
||||
|
||||
return 0 unless $in_type eq $got_type;
|
||||
|
||||
# Don't let overloading mess with us.
|
||||
return refaddr($in) == refaddr($got);
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Test2::Compare::Ref - Ref comparison
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Used to compare two refs in a deep comparison.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
my $ref = {};
|
||||
my $check = Test2::Compare::Ref->new(input => $ref);
|
||||
|
||||
# Passes
|
||||
is( [$ref], [$check], "The array contains the exact ref we want" );
|
||||
|
||||
# Fails, they both may be empty hashes, but we are looking for a specific
|
||||
# reference.
|
||||
is( [{}], [$check], "This will fail");
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Test2-Suite can be found at
|
||||
F<https://github.com/Test-More/Test2-Suite/>.
|
||||
|
||||
=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 2018 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
|
||||
93
database/perl/vendor/lib/Test2/Compare/Regex.pm
vendored
Normal file
93
database/perl/vendor/lib/Test2/Compare/Regex.pm
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
package Test2::Compare::Regex;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use base 'Test2::Compare::Base';
|
||||
|
||||
our $VERSION = '0.000139';
|
||||
|
||||
use Test2::Util::HashBase qw/input/;
|
||||
|
||||
use Test2::Util::Ref qw/render_ref rtype/;
|
||||
use Carp qw/croak/;
|
||||
|
||||
sub init {
|
||||
my $self = shift;
|
||||
|
||||
croak "'input' is a required attribute"
|
||||
unless $self->{+INPUT};
|
||||
|
||||
croak "'input' must be a regex , got '" . $self->{+INPUT} . "'"
|
||||
unless rtype($self->{+INPUT}) eq 'REGEXP';
|
||||
|
||||
$self->SUPER::init();
|
||||
}
|
||||
|
||||
sub stringify_got { 1 }
|
||||
|
||||
sub operator { 'eq' }
|
||||
|
||||
sub name { "" . $_[0]->{+INPUT} }
|
||||
|
||||
sub verify {
|
||||
my $self = shift;
|
||||
my %params = @_;
|
||||
my ($got, $exists) = @params{qw/got exists/};
|
||||
|
||||
return 0 unless $exists;
|
||||
|
||||
my $in = $self->{+INPUT};
|
||||
my $got_type = rtype($got) or return 0;
|
||||
|
||||
return 0 unless $got_type eq 'REGEXP';
|
||||
|
||||
return "$in" eq "$got";
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Test2::Compare::Regex - Regex direct comparison
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Used to compare two regexes. This compares the stringified form of each regex.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Test2-Suite can be found at
|
||||
F<https://github.com/Test-More/Test2-Suite/>.
|
||||
|
||||
=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 2018 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
|
||||
111
database/perl/vendor/lib/Test2/Compare/Scalar.pm
vendored
Normal file
111
database/perl/vendor/lib/Test2/Compare/Scalar.pm
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
package Test2::Compare::Scalar;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use base 'Test2::Compare::Base';
|
||||
|
||||
our $VERSION = '0.000139';
|
||||
|
||||
use Test2::Util::HashBase qw/item/;
|
||||
|
||||
use Carp qw/croak confess/;
|
||||
use Scalar::Util qw/reftype blessed/;
|
||||
|
||||
sub init {
|
||||
my $self = shift;
|
||||
croak "'item' is a required attribute"
|
||||
unless defined $self->{+ITEM};
|
||||
|
||||
$self->SUPER::init();
|
||||
}
|
||||
|
||||
sub name { '<SCALAR>' }
|
||||
sub operator { '${...}' }
|
||||
|
||||
sub verify {
|
||||
my $self = shift;
|
||||
my %params = @_;
|
||||
my ($got, $exists) = @params{qw/got exists/};
|
||||
|
||||
return 0 unless $exists;
|
||||
return 0 unless defined $got;
|
||||
return 0 unless ref($got);
|
||||
return 0 unless reftype($got) eq 'SCALAR' || reftype($got) eq 'VSTRING';
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub deltas {
|
||||
my $self = shift;
|
||||
my %params = @_;
|
||||
my ($got, $convert, $seen) = @params{qw/got convert seen/};
|
||||
|
||||
my $item = $self->{+ITEM};
|
||||
my $check = $convert->($item);
|
||||
|
||||
return (
|
||||
$check->run(
|
||||
id => ['SCALAR' => '$*'],
|
||||
got => $$got,
|
||||
convert => $convert,
|
||||
seen => $seen,
|
||||
exists => 1,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Test2::Compare::Scalar - Representation of a Scalar Ref in deep
|
||||
comparisons
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This is used in deep comparisons to represent a scalar reference.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
my $sr = Test2::Compare::Scalar->new(item => 'foo');
|
||||
|
||||
is([\'foo'], $sr, "pass");
|
||||
is([\'bar'], $sr, "fail, different value");
|
||||
is(['foo'], $sr, "fail, not a ref");
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Test2-Suite can be found at
|
||||
F<https://github.com/Test-More/Test2-Suite/>.
|
||||
|
||||
=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 2018 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
|
||||
153
database/perl/vendor/lib/Test2/Compare/Set.pm
vendored
Normal file
153
database/perl/vendor/lib/Test2/Compare/Set.pm
vendored
Normal file
@@ -0,0 +1,153 @@
|
||||
package Test2::Compare::Set;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use base 'Test2::Compare::Base';
|
||||
|
||||
our $VERSION = '0.000139';
|
||||
|
||||
use Test2::Util::HashBase qw/checks _reduction/;
|
||||
|
||||
use Test2::Compare::Delta();
|
||||
|
||||
use Carp qw/croak confess/;
|
||||
use Scalar::Util qw/reftype/;
|
||||
|
||||
sub init {
|
||||
my $self = shift;
|
||||
|
||||
my $reduction = delete $self->{reduction} || 'any';
|
||||
|
||||
$self->{+CHECKS} ||= [];
|
||||
|
||||
$self->set_reduction($reduction);
|
||||
|
||||
$self->SUPER::init();
|
||||
}
|
||||
|
||||
sub name { '<CHECK-SET>' }
|
||||
sub operator { $_[0]->{+_REDUCTION} }
|
||||
sub reduction { $_[0]->{+_REDUCTION} }
|
||||
|
||||
my %VALID = (any => 1, all => 1, none => 1);
|
||||
sub set_reduction {
|
||||
my $self = shift;
|
||||
my ($redu) = @_;
|
||||
|
||||
croak "'$redu' is not a valid set reduction"
|
||||
unless $VALID{$redu};
|
||||
|
||||
$self->{+_REDUCTION} = $redu;
|
||||
}
|
||||
|
||||
sub verify {
|
||||
my $self = shift;
|
||||
my %params = @_;
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub add_check {
|
||||
my $self = shift;
|
||||
push @{$self->{+CHECKS}} => @_;
|
||||
}
|
||||
|
||||
sub deltas {
|
||||
my $self = shift;
|
||||
my %params = @_;
|
||||
|
||||
my $checks = $self->{+CHECKS};
|
||||
my $reduction = $self->{+_REDUCTION};
|
||||
my $convert = $params{convert};
|
||||
|
||||
unless ($checks && @$checks) {
|
||||
my $file = $self->file;
|
||||
my $lines = $self->lines;
|
||||
|
||||
my $extra = "";
|
||||
if ($file and $lines and @$lines) {
|
||||
my $lns = (@$lines > 1 ? 'lines ' : 'line ' ) . join ', ', @$lines;
|
||||
$extra = " (Set defined in $file $lns)";
|
||||
}
|
||||
|
||||
die "No checks defined for set$extra\n";
|
||||
}
|
||||
|
||||
my @deltas;
|
||||
my $i = 0;
|
||||
for my $check (@$checks) {
|
||||
my $c = $convert->($check);
|
||||
my $id = [META => "Check " . $i++];
|
||||
my @d = $c->run(%params, id => $id);
|
||||
|
||||
if ($reduction eq 'any') {
|
||||
return () unless @d;
|
||||
push @deltas => @d;
|
||||
}
|
||||
elsif ($reduction eq 'all') {
|
||||
push @deltas => @d;
|
||||
}
|
||||
elsif ($reduction eq 'none') {
|
||||
push @deltas => Test2::Compare::Delta->new(
|
||||
verified => 0,
|
||||
id => $id,
|
||||
got => $params{got},
|
||||
check => $c,
|
||||
) unless @d;
|
||||
}
|
||||
else {
|
||||
die "Invalid reduction: $reduction\n";
|
||||
}
|
||||
}
|
||||
|
||||
return @deltas;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Test2::Compare::Set - Allows a field to be matched against a set of
|
||||
checks.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This module is used by the C<check_set> function in the
|
||||
L<Test2::Tools::Compare> plugin.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Test2-Suite can be found at
|
||||
F<https://github.com/Test-More/Test2-Suite/>.
|
||||
|
||||
=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 2018 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
|
||||
108
database/perl/vendor/lib/Test2/Compare/String.pm
vendored
Normal file
108
database/perl/vendor/lib/Test2/Compare/String.pm
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
package Test2::Compare::String;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Carp qw/confess/;
|
||||
|
||||
use base 'Test2::Compare::Base';
|
||||
|
||||
our $VERSION = '0.000139';
|
||||
|
||||
use Test2::Util::HashBase qw/input/;
|
||||
|
||||
# Overloads '!' for us.
|
||||
use Test2::Compare::Negatable;
|
||||
|
||||
sub stringify_got { 1 }
|
||||
|
||||
sub init {
|
||||
my $self = shift;
|
||||
confess "input must be defined for 'String' check"
|
||||
unless defined $self->{+INPUT};
|
||||
|
||||
$self->SUPER::init(@_);
|
||||
}
|
||||
|
||||
sub name {
|
||||
my $self = shift;
|
||||
my $in = $self->{+INPUT};
|
||||
return "$in";
|
||||
}
|
||||
|
||||
sub operator {
|
||||
my $self = shift;
|
||||
|
||||
return '' unless @_;
|
||||
my ($got) = @_;
|
||||
|
||||
return '' unless defined($got);
|
||||
|
||||
return 'ne' if $self->{+NEGATE};
|
||||
return 'eq';
|
||||
}
|
||||
|
||||
sub verify {
|
||||
my $self = shift;
|
||||
my %params = @_;
|
||||
my ($got, $exists) = @params{qw/got exists/};
|
||||
|
||||
return 0 unless $exists;
|
||||
return 0 unless defined $got;
|
||||
|
||||
my $input = $self->{+INPUT};
|
||||
my $negate = $self->{+NEGATE};
|
||||
|
||||
return "$input" ne "$got" if $negate;
|
||||
return "$input" eq "$got";
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Test2::Compare::String - Compare two values as strings
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This is used to compare two items after they are stringified. You can also check
|
||||
that two strings are not equal.
|
||||
|
||||
B<Note>: This will fail if the received value is undefined, it must be defined.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Test2-Suite can be found at
|
||||
F<https://github.com/Test-More/Test2-Suite/>.
|
||||
|
||||
=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 2018 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
|
||||
83
database/perl/vendor/lib/Test2/Compare/Undef.pm
vendored
Normal file
83
database/perl/vendor/lib/Test2/Compare/Undef.pm
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
package Test2::Compare::Undef;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Carp qw/confess/;
|
||||
|
||||
use base 'Test2::Compare::Base';
|
||||
|
||||
our $VERSION = '0.000139';
|
||||
|
||||
use Test2::Util::HashBase;
|
||||
|
||||
# Overloads '!' for us.
|
||||
use Test2::Compare::Negatable;
|
||||
|
||||
sub name { '<UNDEF>' }
|
||||
|
||||
sub operator {
|
||||
my $self = shift;
|
||||
|
||||
return 'IS NOT' if $self->{+NEGATE};
|
||||
return 'IS';
|
||||
}
|
||||
|
||||
sub verify {
|
||||
my $self = shift;
|
||||
my %params = @_;
|
||||
my ($got, $exists) = @params{qw/got exists/};
|
||||
|
||||
return 0 unless $exists;
|
||||
|
||||
return !defined($got) unless $self->{+NEGATE};
|
||||
return defined($got);
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Test2::Compare::Undef - Check that something is undefined
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Make sure something is undefined in a comparison. You can also check that
|
||||
something is defined.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Test2-Suite can be found at
|
||||
F<https://github.com/Test-More/Test2-Suite/>.
|
||||
|
||||
=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 2018 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
|
||||
69
database/perl/vendor/lib/Test2/Compare/Wildcard.pm
vendored
Normal file
69
database/perl/vendor/lib/Test2/Compare/Wildcard.pm
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
package Test2::Compare::Wildcard;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use base 'Test2::Compare::Base';
|
||||
|
||||
our $VERSION = '0.000139';
|
||||
|
||||
use Test2::Util::HashBase qw/expect/;
|
||||
|
||||
use Carp qw/croak/;
|
||||
|
||||
sub init {
|
||||
my $self = shift;
|
||||
croak "'expect' is a require attribute"
|
||||
unless exists $self->{+EXPECT};
|
||||
|
||||
$self->SUPER::init();
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Test2::Compare::Wildcard - Placeholder check.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This module is used as a temporary placeholder for values that still need to be
|
||||
converted. This is necessary to carry forward the filename and line number which
|
||||
would be lost in the conversion otherwise.
|
||||
|
||||
=head1 SOURCE
|
||||
|
||||
The source code repository for Test2-Suite can be found at
|
||||
F<https://github.com/Test-More/Test2-Suite/>.
|
||||
|
||||
=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 2018 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