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   1844 use strict;
  169         366  
  169         5088  
3 169     169   861 use warnings;
  169         357  
  169         6740  
4              
5             our $VERSION = '0.000156';
6              
7 169     169   933 use Scalar::Util qw/blessed/;
  169         467  
  169         9611  
8 169     169   1363 use Test2::Util qw/try/;
  169         534  
  169         8840  
9 169     169   3730 use Test2::Util::Ref qw/rtype/;
  169         411  
  169         8216  
10              
11 169     169   1213 use Carp qw/croak/;
  169         423  
  169         13907  
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   1273 use base 'Exporter';
  169         354  
  169         210976  
19              
20             sub compare {
21 1785     1785 1 7997 my ($got, $check, $convert) = @_;
22              
23 1785         4768 $check = $convert->($check);
24              
25 1785         13008 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 8832 100   8832 1 27587 sub get_build { @BUILD ? $BUILD[-1] : undef }
37 1     1 1 5 sub push_build { push @BUILD => $_[0] }
38              
39             sub pop_build {
40 4 100 100 4 1 63 return pop @BUILD if @BUILD && $_[0] && $BUILD[-1] == $_[0];
      100        
41 3 100       16 my $have = @BUILD ? "$BUILD[-1]" : 'undef';
42 3 100       20 my $want = $_[0] ? "$_[0]" : 'undef';
43 3         607 croak "INTERNAL ERROR: Attempted to pop incorrect build, have $have, tried to pop $want";
44             }
45              
46             sub build {
47 2524     2524 1 6039 my ($class, $code) = @_;
48              
49 2524         18559 my @caller = caller(1);
50              
51 2524 100       7339 die "'$caller[3]\()' should not be called in void context in $caller[1] line $caller[2]\n"
52             unless defined(wantarray);
53              
54 2523         11179 my $build = $class->new(builder => $code, called => \@caller);
55              
56 2523         8871 push @BUILD => $build;
57 2523     2523   13859 my ($ok, $err) = try { $code->($build); 1 };
  2523         31766  
  2509         8042  
58 2523         21539 pop @BUILD;
59 2523 100       5308 die $err unless $ok;
60              
61 2509         9688 return $build;
62             }
63              
64 11924     11924 1 41151 sub strict_convert { convert($_[0], { implicit_end => 1, use_regex => 0, use_code => 0 }) }
65 3157     3157 1 10772 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 15082     15082 1 27483 my ($thing, $config) = @_;
71              
72 15082 100       30839 unless($CONVERT_LOADED) {
73 117         1983 require Test2::Compare::Array;
74 117         712 require Test2::Compare::Base;
75 117         1046 require Test2::Compare::Custom;
76 117         2271 require Test2::Compare::DeepRef;
77 117         965 require Test2::Compare::Hash;
78 117         961 require Test2::Compare::Pattern;
79 117         982 require Test2::Compare::Ref;
80 117         989 require Test2::Compare::Regex;
81 117         945 require Test2::Compare::Scalar;
82 117         1387 require Test2::Compare::String;
83 117         1018 require Test2::Compare::Undef;
84 117         969 require Test2::Compare::Wildcard;
85 117         461 $CONVERT_LOADED = 1;
86             }
87              
88 15082 100       30108 if (ref($config)) {
89 15081         42623 my $bad = join ', ' => grep { !$ALLOWED_KEYS{$_} } keys %$config;
  45243         95280  
90 15081 50       31623 croak "The following config options are not understood by convert(): $bad" if $bad;
91 15081 50       29625 $config->{implicit_end} = 1 unless defined $config->{implicit_end};
92 15081 50       27313 $config->{use_regex} = 1 unless defined $config->{use_regex};
93 15081 50       28189 $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         4 $config = {
105             implicit_end => 0,
106             use_regex => 1,
107             use_code => 1,
108             };
109             }
110             }
111              
112 15082         29881 return _convert($thing, $config);
113             }
114              
115             sub _convert {
116 20467     20467   46887 my ($thing, $config) = @_;
117              
118 20467 100       36228 return Test2::Compare::Undef->new()
119             unless defined $thing;
120              
121 20267 100 100     85837 if (blessed($thing) && $thing->isa('Test2::Compare::Base')) {
122 10453 100 100     47840 if ($config->{implicit_end} && $thing->can('set_ending') && !defined $thing->ending) {
      100        
123 157         1116 my $clone = $thing->clone;
124 157         508 $clone->set_ending('implicit');
125 157         762 return $clone;
126             }
127              
128 10296 100       48326 return $thing unless $thing->isa('Test2::Compare::Wildcard');
129 5372         13844 my $newthing = _convert($thing->expect, $config);
130 5372 100       19694 $newthing->set_builder($thing->builder) unless $newthing->builder;
131 5372 100       38743 $newthing->set_file($thing->_file) unless $newthing->_file;
132 5372 100       43447 $newthing->set_lines($thing->_lines) unless $newthing->_lines;
133 5372         44121 return $newthing;
134             }
135              
136 9814         23369 my $type = rtype($thing);
137              
138 9814 100       23625 return Test2::Compare::Array->new(inref => $thing, $config->{implicit_end} ? (ending => 1) : ())
    100          
139             if $type eq 'ARRAY';
140              
141 9387 100       18635 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 9052 100 100     24248 ) if $config->{use_regex} && $type eq 'REGEXP';
148              
149             return Test2::Compare::Custom->new(code => $thing)
150 8814 100 100     19167 if $config->{use_code} && $type eq 'CODE';
151              
152 8812 100       16620 return Test2::Compare::Regex->new(input => $thing)
153             if $type eq 'REGEXP';
154              
155 8808 100 100     26122 if ($type eq 'SCALAR' || $type eq 'VSTRING') {
156 13         62 my $nested = _convert($$thing, $config);
157 13         90 return Test2::Compare::Scalar->new(item => $nested);
158             }
159              
160 8795 100       15923 return Test2::Compare::DeepRef->new(input => $thing)
161             if $type eq 'REF';
162              
163 8791 100       15750 return Test2::Compare::Ref->new(input => $thing)
164             if $type;
165              
166             # is() will assume string and use 'eq'
167 8759         26821 return Test2::Compare::String->new(input => $thing);
168             }
169              
170             1;
171              
172             __END__