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 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__