File Coverage

blib/lib/Test2/Compare.pm
Criterion Covered Total %
statement 93 94 98.9
branch 55 60 91.6
condition 24 24 100.0
subroutine 17 17 100.0
pod 8 8 100.0
total 197 203 97.0


line stmt bran cond sub pod time code
1             package Test2::Compare;
2 169     169   1750 use strict;
  169         340  
  169         4727  
3 169     169   924 use warnings;
  169         392  
  169         6723  
4              
5             our $VERSION = '0.000155';
6              
7 169     169   961 use Scalar::Util qw/blessed/;
  169         606  
  169         9356  
8 169     169   1275 use Test2::Util qw/try/;
  169         386  
  169         8267  
9 169     169   3568 use Test2::Util::Ref qw/rtype/;
  169         444  
  169         7844  
10              
11 169     169   1137 use Carp qw/croak/;
  169         541  
  169         13503  
12              
13             our @EXPORT_OK = qw{
14             compare
15             get_build push_build pop_build build
16             strict_convert relaxed_convert convert
17             };
18 169     169   1181 use base 'Exporter';
  169         748  
  169         204347  
19              
20             sub compare {
21 1761     1761 1 4973 my ($got, $check, $convert) = @_;
22              
23 1761         7580 $check = $convert->($check);
24              
25 1761         12786 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 8608 100   8608 1 28027 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       11 my $have = @BUILD ? "$BUILD[-1]" : 'undef';
42 3 100       13 my $want = $_[0] ? "$_[0]" : 'undef';
43 3         395 croak "INTERNAL ERROR: Attempted to pop incorrect build, have $have, tried to pop $want";
44             }
45              
46             sub build {
47 2448     2448 1 5661 my ($class, $code) = @_;
48              
49 2448         17401 my @caller = caller(1);
50              
51 2448 100       7741 die "'$caller[3]\()' should not be called in void context in $caller[1] line $caller[2]\n"
52             unless defined(wantarray);
53              
54 2447         10749 my $build = $class->new(builder => $code, called => \@caller);
55              
56 2447         8608 push @BUILD => $build;
57 2447     2447   14228 my ($ok, $err) = try { $code->($build); 1 };
  2447         31737  
  2433         7858  
58 2447         21279 pop @BUILD;
59 2447 100       5347 die $err unless $ok;
60              
61 2433         9710 return $build;
62             }
63              
64 11900     11900 1 41050 sub strict_convert { convert($_[0], { implicit_end => 1, use_regex => 0, use_code => 0 }) }
65 2981     2981 1 10143 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 14882     14882 1 27623 my ($thing, $config) = @_;
71              
72 14882 100       30018 unless($CONVERT_LOADED) {
73 117         1941 require Test2::Compare::Array;
74 117         737 require Test2::Compare::Base;
75 117         1023 require Test2::Compare::Custom;
76 117         2231 require Test2::Compare::DeepRef;
77 117         1084 require Test2::Compare::Hash;
78 117         1024 require Test2::Compare::Pattern;
79 117         1005 require Test2::Compare::Ref;
80 117         930 require Test2::Compare::Regex;
81 117         978 require Test2::Compare::Scalar;
82 117         911 require Test2::Compare::String;
83 117         1109 require Test2::Compare::Undef;
84 117         916 require Test2::Compare::Wildcard;
85 117         451 $CONVERT_LOADED = 1;
86             }
87              
88 14882 100       29992 if (ref($config)) {
89 14881         42627 my $bad = join ', ' => grep { !$ALLOWED_KEYS{$_} } keys %$config;
  44643         94383  
90 14881 50       32748 croak "The following config options are not understood by convert(): $bad" if $bad;
91 14881 50       29533 $config->{implicit_end} = 1 unless defined $config->{implicit_end};
92 14881 50       27937 $config->{use_regex} = 1 unless defined $config->{use_regex};
93 14881 50       28338 $config->{use_code} = 0 unless defined $config->{use_code};
94             }
95             else { # Legacy...
96 1 50       3 if ($config) {
97 0         0 $config = {
98             implicit_end => 1,
99             use_regex => 0,
100             use_code => 0,
101             };
102             }
103             else {
104 1         5 $config = {
105             implicit_end => 0,
106             use_regex => 1,
107             use_code => 1,
108             };
109             }
110             }
111              
112 14882         29293 return _convert($thing, $config);
113             }
114              
115             sub _convert {
116 20123     20123   44993 my ($thing, $config) = @_;
117              
118 20123 100       36847 return Test2::Compare::Undef->new()
119             unless defined $thing;
120              
121 19923 100 100     82084 if (blessed($thing) && $thing->isa('Test2::Compare::Base')) {
122 10209 100 100     46793 if ($config->{implicit_end} && $thing->can('set_ending') && !defined $thing->ending) {
      100        
123 157         1099 my $clone = $thing->clone;
124 157         528 $clone->set_ending('implicit');
125 157         712 return $clone;
126             }
127              
128 10052 100       45343 return $thing unless $thing->isa('Test2::Compare::Wildcard');
129 5228         12461 my $newthing = _convert($thing->expect, $config);
130 5228 100       19601 $newthing->set_builder($thing->builder) unless $newthing->builder;
131 5228 100       39138 $newthing->set_file($thing->_file) unless $newthing->_file;
132 5228 100       42026 $newthing->set_lines($thing->_lines) unless $newthing->_lines;
133 5228         42597 return $newthing;
134             }
135              
136 9714         22597 my $type = rtype($thing);
137              
138 9714 100       23885 return Test2::Compare::Array->new(inref => $thing, $config->{implicit_end} ? (ending => 1) : ())
    100          
139             if $type eq 'ARRAY';
140              
141 9291 100       18524 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     23585 ) if $config->{use_regex} && $type eq 'REGEXP';
148              
149             return Test2::Compare::Custom->new(code => $thing)
150 8718 100 100     19167 if $config->{use_code} && $type eq 'CODE';
151              
152 8716 100       15878 return Test2::Compare::Regex->new(input => $thing)
153             if $type eq 'REGEXP';
154              
155 8712 100 100     26025 if ($type eq 'SCALAR' || $type eq 'VSTRING') {
156 13         71 my $nested = _convert($$thing, $config);
157 13         69 return Test2::Compare::Scalar->new(item => $nested);
158             }
159              
160 8699 100       15858 return Test2::Compare::DeepRef->new(input => $thing)
161             if $type eq 'REF';
162              
163 8695 100       15573 return Test2::Compare::Ref->new(input => $thing)
164             if $type;
165              
166             # is() will assume string and use 'eq'
167 8663         25459 return Test2::Compare::String->new(input => $thing);
168             }
169              
170             1;
171              
172             __END__