| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Test2::Compare; | 
| 2 | 168 |  |  | 168 |  | 1675 | use strict; | 
|  | 168 |  |  |  |  | 299 |  | 
|  | 168 |  |  |  |  | 4544 |  | 
| 3 | 168 |  |  | 168 |  | 770 | use warnings; | 
|  | 168 |  |  |  |  | 337 |  | 
|  | 168 |  |  |  |  | 6685 |  | 
| 4 |  |  |  |  |  |  |  | 
| 5 |  |  |  |  |  |  | our $VERSION = '0.000153'; | 
| 6 |  |  |  |  |  |  |  | 
| 7 | 168 |  |  | 168 |  | 964 | use Scalar::Util qw/blessed/; | 
|  | 168 |  |  |  |  | 385 |  | 
|  | 168 |  |  |  |  | 8645 |  | 
| 8 | 168 |  |  | 168 |  | 1058 | use Test2::Util qw/try/; | 
|  | 168 |  |  |  |  | 363 |  | 
|  | 168 |  |  |  |  | 7213 |  | 
| 9 | 168 |  |  | 168 |  | 3428 | use Test2::Util::Ref qw/rtype/; | 
|  | 168 |  |  |  |  | 374 |  | 
|  | 168 |  |  |  |  | 8069 |  | 
| 10 |  |  |  |  |  |  |  | 
| 11 | 168 |  |  | 168 |  | 1076 | use Carp qw/croak/; | 
|  | 168 |  |  |  |  | 400 |  | 
|  | 168 |  |  |  |  | 12341 |  | 
| 12 |  |  |  |  |  |  |  | 
| 13 |  |  |  |  |  |  | our @EXPORT_OK = qw{ | 
| 14 |  |  |  |  |  |  | compare | 
| 15 |  |  |  |  |  |  | get_build push_build pop_build build | 
| 16 |  |  |  |  |  |  | strict_convert relaxed_convert convert | 
| 17 |  |  |  |  |  |  | }; | 
| 18 | 168 |  |  | 168 |  | 1093 | use base 'Exporter'; | 
|  | 168 |  |  |  |  | 453 |  | 
|  | 168 |  |  |  |  | 190247 |  | 
| 19 |  |  |  |  |  |  |  | 
| 20 |  |  |  |  |  |  | sub compare { | 
| 21 | 1758 |  |  | 1758 | 1 | 4703 | my ($got, $check, $convert) = @_; | 
| 22 |  |  |  |  |  |  |  | 
| 23 | 1758 |  |  |  |  | 7348 | $check = $convert->($check); | 
| 24 |  |  |  |  |  |  |  | 
| 25 | 1758 |  |  |  |  | 11475 | return $check->run( | 
| 26 |  |  |  |  |  |  | id      => undef, | 
| 27 |  |  |  |  |  |  | got     => $got, | 
| 28 |  |  |  |  |  |  | exists  => 1, | 
| 29 |  |  |  |  |  |  | convert => $convert, | 
| 30 |  |  |  |  |  |  | seen    => {}, | 
| 31 |  |  |  |  |  |  | ); | 
| 32 |  |  |  |  |  |  | } | 
| 33 |  |  |  |  |  |  |  | 
| 34 |  |  |  |  |  |  | my @BUILD; | 
| 35 |  |  |  |  |  |  |  | 
| 36 | 8602 | 100 |  | 8602 | 1 | 24873 | sub get_build  { @BUILD ? $BUILD[-1] : undef } | 
| 37 | 1 |  |  | 1 | 1 | 3 | sub push_build { push @BUILD => $_[0] } | 
| 38 |  |  |  |  |  |  |  | 
| 39 |  |  |  |  |  |  | sub pop_build { | 
| 40 | 4 | 100 | 100 | 4 | 1 | 43 | return pop @BUILD if @BUILD && $_[0] && $BUILD[-1] == $_[0]; | 
|  |  |  | 100 |  |  |  |  | 
| 41 | 3 | 100 |  |  |  | 13 | my $have = @BUILD ? "$BUILD[-1]" : 'undef'; | 
| 42 | 3 | 100 |  |  |  | 25 | my $want = $_[0]  ? "$_[0]"      : 'undef'; | 
| 43 | 3 |  |  |  |  | 398 | croak "INTERNAL ERROR: Attempted to pop incorrect build, have $have, tried to pop $want"; | 
| 44 |  |  |  |  |  |  | } | 
| 45 |  |  |  |  |  |  |  | 
| 46 |  |  |  |  |  |  | sub build { | 
| 47 | 2444 |  |  | 2444 | 1 | 5192 | my ($class, $code) = @_; | 
| 48 |  |  |  |  |  |  |  | 
| 49 | 2444 |  |  |  |  | 15655 | my @caller = caller(1); | 
| 50 |  |  |  |  |  |  |  | 
| 51 | 2444 | 100 |  |  |  | 6364 | die "'$caller[3]\()' should not be called in void context in $caller[1] line $caller[2]\n" | 
| 52 |  |  |  |  |  |  | unless defined(wantarray); | 
| 53 |  |  |  |  |  |  |  | 
| 54 | 2443 |  |  |  |  | 9934 | my $build = $class->new(builder => $code, called => \@caller); | 
| 55 |  |  |  |  |  |  |  | 
| 56 | 2443 |  |  |  |  | 7566 | push @BUILD => $build; | 
| 57 | 2443 |  |  | 2443 |  | 12703 | my ($ok, $err) = try { $code->($build); 1 }; | 
|  | 2443 |  |  |  |  | 28089 |  | 
|  | 2429 |  |  |  |  | 7054 |  | 
| 58 | 2443 |  |  |  |  | 19466 | pop @BUILD; | 
| 59 | 2443 | 100 |  |  |  | 4637 | die $err unless $ok; | 
| 60 |  |  |  |  |  |  |  | 
| 61 | 2429 |  |  |  |  | 8038 | return $build; | 
| 62 |  |  |  |  |  |  | } | 
| 63 |  |  |  |  |  |  |  | 
| 64 | 11891 |  |  | 11891 | 1 | 39317 | sub strict_convert  { convert($_[0], { implicit_end => 1, use_regex => 0, use_code => 0 }) } | 
| 65 | 2981 |  |  | 2981 | 1 | 8786 | sub relaxed_convert { convert($_[0], { implicit_end => 0, use_regex => 1, use_code => 1 }) } | 
| 66 |  |  |  |  |  |  |  | 
| 67 |  |  |  |  |  |  | my $CONVERT_LOADED = 0; | 
| 68 |  |  |  |  |  |  | my %ALLOWED_KEYS = ( implicit_end => 1, use_regex => 1, use_code => 1 ); | 
| 69 |  |  |  |  |  |  | sub convert { | 
| 70 | 14873 |  |  | 14873 | 1 | 26137 | my ($thing, $config) = @_; | 
| 71 |  |  |  |  |  |  |  | 
| 72 | 14873 | 100 |  |  |  | 27524 | unless($CONVERT_LOADED) { | 
| 73 | 116 |  |  |  |  | 1830 | require Test2::Compare::Array; | 
| 74 | 116 |  |  |  |  | 646 | require Test2::Compare::Base; | 
| 75 | 116 |  |  |  |  | 930 | require Test2::Compare::Custom; | 
| 76 | 116 |  |  |  |  | 2085 | require Test2::Compare::DeepRef; | 
| 77 | 116 |  |  |  |  | 924 | require Test2::Compare::Hash; | 
| 78 | 116 |  |  |  |  | 896 | require Test2::Compare::Pattern; | 
| 79 | 116 |  |  |  |  | 887 | require Test2::Compare::Ref; | 
| 80 | 116 |  |  |  |  | 816 | require Test2::Compare::Regex; | 
| 81 | 116 |  |  |  |  | 924 | require Test2::Compare::Scalar; | 
| 82 | 116 |  |  |  |  | 851 | require Test2::Compare::String; | 
| 83 | 116 |  |  |  |  | 1077 | require Test2::Compare::Undef; | 
| 84 | 116 |  |  |  |  | 881 | require Test2::Compare::Wildcard; | 
| 85 | 116 |  |  |  |  | 399 | $CONVERT_LOADED = 1; | 
| 86 |  |  |  |  |  |  | } | 
| 87 |  |  |  |  |  |  |  | 
| 88 | 14873 | 100 |  |  |  | 27906 | if (ref($config)) { | 
| 89 | 14872 |  |  |  |  | 39741 | my $bad = join ', ' => grep { !$ALLOWED_KEYS{$_} } keys %$config; | 
|  | 44616 |  |  |  |  | 89929 |  | 
| 90 | 14872 | 50 |  |  |  | 30700 | croak "The following config options are not understood by convert(): $bad" if $bad; | 
| 91 | 14872 | 50 |  |  |  | 27170 | $config->{implicit_end} = 1 unless defined $config->{implicit_end}; | 
| 92 | 14872 | 50 |  |  |  | 25224 | $config->{use_regex}    = 1 unless defined $config->{use_regex}; | 
| 93 | 14872 | 50 |  |  |  | 25839 | $config->{use_code}     = 0 unless defined $config->{use_code}; | 
| 94 |  |  |  |  |  |  | } | 
| 95 |  |  |  |  |  |  | else { # Legacy... | 
| 96 | 1 | 50 |  |  |  | 9 | if ($config) { | 
| 97 | 0 |  |  |  |  | 0 | $config = { | 
| 98 |  |  |  |  |  |  | implicit_end => 1, | 
| 99 |  |  |  |  |  |  | use_regex  => 0, | 
| 100 |  |  |  |  |  |  | use_code   => 0, | 
| 101 |  |  |  |  |  |  | }; | 
| 102 |  |  |  |  |  |  | } | 
| 103 |  |  |  |  |  |  | else { | 
| 104 | 1 |  |  |  |  | 9 | $config = { | 
| 105 |  |  |  |  |  |  | implicit_end => 0, | 
| 106 |  |  |  |  |  |  | use_regex  => 1, | 
| 107 |  |  |  |  |  |  | use_code   => 1, | 
| 108 |  |  |  |  |  |  | }; | 
| 109 |  |  |  |  |  |  | } | 
| 110 |  |  |  |  |  |  | } | 
| 111 |  |  |  |  |  |  |  | 
| 112 | 14873 |  |  |  |  | 27966 | return _convert($thing, $config); | 
| 113 |  |  |  |  |  |  | } | 
| 114 |  |  |  |  |  |  |  | 
| 115 |  |  |  |  |  |  | sub _convert { | 
| 116 | 20112 |  |  | 20112 |  | 42821 | my ($thing, $config) = @_; | 
| 117 |  |  |  |  |  |  |  | 
| 118 | 20112 | 100 |  |  |  | 70269 | return Test2::Compare::Undef->new() | 
| 119 |  |  |  |  |  |  | unless defined $thing; | 
| 120 |  |  |  |  |  |  |  | 
| 121 | 19912 | 100 | 100 |  |  | 77713 | if (blessed($thing) && $thing->isa('Test2::Compare::Base')) { | 
| 122 | 10199 | 100 | 100 |  |  | 43116 | if ($config->{implicit_end} && $thing->can('set_ending') && !defined $thing->ending) { | 
|  |  |  | 100 |  |  |  |  | 
| 123 | 157 |  |  |  |  | 1079 | my $clone = $thing->clone; | 
| 124 | 157 |  |  |  |  | 543 | $clone->set_ending('implicit'); | 
| 125 | 157 |  |  |  |  | 698 | return $clone; | 
| 126 |  |  |  |  |  |  | } | 
| 127 |  |  |  |  |  |  |  | 
| 128 | 10042 | 100 |  |  |  | 44166 | return $thing unless $thing->isa('Test2::Compare::Wildcard'); | 
| 129 | 5226 |  |  |  |  | 11370 | my $newthing = _convert($thing->expect, $config); | 
| 130 | 5226 | 100 |  |  |  | 17446 | $newthing->set_builder($thing->builder) unless $newthing->builder; | 
| 131 | 5226 | 100 |  |  |  | 34731 | $newthing->set_file($thing->_file)      unless $newthing->_file; | 
| 132 | 5226 | 100 |  |  |  | 38052 | $newthing->set_lines($thing->_lines)    unless $newthing->_lines; | 
| 133 | 5226 |  |  |  |  | 39074 | return $newthing; | 
| 134 |  |  |  |  |  |  | } | 
| 135 |  |  |  |  |  |  |  | 
| 136 | 9713 |  |  |  |  | 21637 | my $type = rtype($thing); | 
| 137 |  |  |  |  |  |  |  | 
| 138 | 9713 | 100 |  |  |  | 22182 | return Test2::Compare::Array->new(inref => $thing, $config->{implicit_end} ? (ending => 1) : ()) | 
|  |  | 100 |  |  |  |  |  | 
| 139 |  |  |  |  |  |  | if $type eq 'ARRAY'; | 
| 140 |  |  |  |  |  |  |  | 
| 141 | 9291 | 100 |  |  |  | 17162 | return Test2::Compare::Hash->new(inref => $thing, $config->{implicit_end} ? (ending => 1) : ()) | 
|  |  | 100 |  |  |  |  |  | 
| 142 |  |  |  |  |  |  | if $type eq 'HASH'; | 
| 143 |  |  |  |  |  |  |  | 
| 144 |  |  |  |  |  |  | return Test2::Compare::Pattern->new( | 
| 145 |  |  |  |  |  |  | pattern       => $thing, | 
| 146 |  |  |  |  |  |  | stringify_got => 1, | 
| 147 | 8956 | 100 | 100 |  |  | 21832 | ) if $config->{use_regex} && $type eq 'REGEXP'; | 
| 148 |  |  |  |  |  |  |  | 
| 149 |  |  |  |  |  |  | return Test2::Compare::Custom->new(code => $thing) | 
| 150 | 8718 | 100 | 100 |  |  | 18384 | if $config->{use_code} && $type eq 'CODE'; | 
| 151 |  |  |  |  |  |  |  | 
| 152 | 8716 | 100 |  |  |  | 15064 | return Test2::Compare::Regex->new(input => $thing) | 
| 153 |  |  |  |  |  |  | if $type eq 'REGEXP'; | 
| 154 |  |  |  |  |  |  |  | 
| 155 | 8712 | 100 | 100 |  |  | 25649 | if ($type eq 'SCALAR' || $type eq 'VSTRING') { | 
| 156 | 13 |  |  |  |  | 57 | my $nested = _convert($$thing, $config); | 
| 157 | 13 |  |  |  |  | 66 | return Test2::Compare::Scalar->new(item => $nested); | 
| 158 |  |  |  |  |  |  | } | 
| 159 |  |  |  |  |  |  |  | 
| 160 | 8699 | 100 |  |  |  | 15050 | return Test2::Compare::DeepRef->new(input => $thing) | 
| 161 |  |  |  |  |  |  | if $type eq 'REF'; | 
| 162 |  |  |  |  |  |  |  | 
| 163 | 8695 | 100 |  |  |  | 14560 | return Test2::Compare::Ref->new(input => $thing) | 
| 164 |  |  |  |  |  |  | if $type; | 
| 165 |  |  |  |  |  |  |  | 
| 166 |  |  |  |  |  |  | # is() will assume string and use 'eq' | 
| 167 | 8663 |  |  |  |  | 25059 | return Test2::Compare::String->new(input => $thing); | 
| 168 |  |  |  |  |  |  | } | 
| 169 |  |  |  |  |  |  |  | 
| 170 |  |  |  |  |  |  | 1; | 
| 171 |  |  |  |  |  |  |  | 
| 172 |  |  |  |  |  |  | __END__ |