File Coverage

blib/lib/Test2/Compare/Float.pm
Criterion Covered Total %
statement 70 71 98.5
branch 39 42 92.8
condition 19 21 90.4
subroutine 11 11 100.0
pod 3 4 75.0
total 142 149 95.3


line stmt bran cond sub pod time code
1             package Test2::Compare::Float;
2 163     163   1079 use strict;
  163         305  
  163         4681  
3 163     163   781 use warnings;
  163         422  
  163         4209  
4              
5 163     163   833 use Carp qw/confess/;
  163         315  
  163         6739  
6              
7 163     163   867 use base 'Test2::Compare::Base';
  163         314  
  163         20002  
8              
9             our $VERSION = '0.000153';
10              
11             our $DEFAULT_TOLERANCE = 1e-08;
12              
13 163     163   1550 use Test2::Util::HashBase qw/input tolerance precision/;
  163         366  
  163         1087  
14              
15             # Overloads '!' for us.
16 163     163   31451 use Test2::Compare::Negatable;
  163         343  
  163         939  
17              
18             sub init {
19 28     28 0 945 my $self = shift;
20 28         126 my $input = $self->{+INPUT};
21              
22 28 100 100     166 if ( exists $self->{+TOLERANCE} and exists $self->{+PRECISION} ) {
    100 100        
23 1         182 confess "can't set both tolerance and precision";
24             } elsif (!exists $self->{+PRECISION} and !exists $self->{+TOLERANCE}) {
25 10         23 $self->{+TOLERANCE} = $DEFAULT_TOLERANCE
26             }
27              
28 27 100       343 confess "input must be defined for 'Float' check"
29             unless defined $input;
30              
31             # Check for ''
32 26 100 100     444 confess "input must be a number for 'Float' check"
33             unless length($input) && $input =~ m/\S/;
34              
35             confess "precision must be an integer for 'Float' check"
36 24 100 100     452 if exists $self->{+PRECISION} && $self->{+PRECISION} !~ m/^\d+$/;
37              
38 22         73 $self->SUPER::init(@_);
39             }
40              
41             sub name {
42 36     36 1 301 my $self = shift;
43 36         63 my $in = $self->{+INPUT};
44 36         72 my $precision = $self->{+PRECISION};
45 36 100       75 if ( defined $precision) {
46 12         148 return sprintf "%.*f", $precision, $in;
47             }
48 24         39 my $tolerance = $self->{+TOLERANCE};
49 24         195 return "$in +/- $tolerance";
50             }
51              
52             sub operator {
53 17     17 1 255 my $self = shift;
54 17 100       52 return '' unless @_;
55 14         25 my ($got) = @_;
56              
57 14 100       37 return '' unless defined($got);
58 11 50 33     67 return '' unless length($got) && $got =~ m/\S/;
59              
60 11 100       31 if ( $self->{+PRECISION} )
61             {
62 1 50       6 return 'ne' if $self->{+NEGATE};
63 1         6 return 'eq';
64             }
65              
66 10 100       32 return '!=' if $self->{+NEGATE};
67 4         15 return '==';
68             }
69              
70             sub verify {
71 78     78 1 781 my $self = shift;
72 78         198 my %params = @_;
73 78         184 my ($got, $exists) = @params{qw/got exists/};
74              
75 78 100       180 return 0 unless $exists;
76 76 100       159 return 0 unless defined $got;
77 74 100       149 return 0 if ref $got;
78 72 100 100     571 return 0 unless length($got) && $got =~ m/\S/;
79              
80 70         152 my $input = $self->{+INPUT};
81 70         119 my $negate = $self->{+NEGATE};
82 70         118 my $tolerance = $self->{+TOLERANCE};
83 70         95 my $precision = $self->{+PRECISION};
84              
85 70         102 my @warnings;
86             my $out;
87             {
88 70     5   104 local $SIG{__WARN__} = sub { push @warnings => @_ };
  70         390  
  5         29  
89              
90 70         284 my $equal = ($input == $got);
91 70 100       157 if (!$equal) {
92 46 100       93 if (defined $tolerance) {
93 32 100 100     118 $equal = 1 if
94             $got > $input - $tolerance &&
95             $got < $input + $tolerance;
96             } else {
97 14         104 $equal =
98             sprintf("%.*f", $precision, $got) eq
99             sprintf("%.*f", $precision, $input);
100             }
101             }
102              
103 70 100       332 $out = $negate ? !$equal : $equal;
104             }
105              
106 70         169 for my $warn (@warnings) {
107 5 50       23 if ($warn =~ m/numeric/) {
108 5         9 $out = 0;
109 5         12 next; # This warning won't help anyone.
110             }
111 0         0 warn $warn;
112             }
113              
114 70         431 return $out;
115             }
116              
117             1;
118              
119             __END__