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 164     164   1190 use strict;
  164         321  
  164         5137  
3 164     164   958 use warnings;
  164         519  
  164         4755  
4              
5 164     164   1199 use Carp qw/confess/;
  164         318  
  164         7474  
6              
7 164     164   931 use base 'Test2::Compare::Base';
  164         349  
  164         19123  
8              
9             our $VERSION = '0.000156';
10              
11             our $DEFAULT_TOLERANCE = 1e-08;
12              
13 164     164   1108 use Test2::Util::HashBase qw/input tolerance precision/;
  164         406  
  164         1060  
14              
15             # Overloads '!' for us.
16 164     164   32174 use Test2::Compare::Negatable;
  164         372  
  164         1004  
17              
18             sub init {
19 28     28 0 1047 my $self = shift;
20 28         146 my $input = $self->{+INPUT};
21              
22 28 100 100     180 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         35 $self->{+TOLERANCE} = $DEFAULT_TOLERANCE
26             }
27              
28 27 100       412 confess "input must be defined for 'Float' check"
29             unless defined $input;
30              
31             # Check for ''
32 26 100 100     482 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     443 if exists $self->{+PRECISION} && $self->{+PRECISION} !~ m/^\d+$/;
37              
38 22         84 $self->SUPER::init(@_);
39             }
40              
41             sub name {
42 36     36 1 342 my $self = shift;
43 36         70 my $in = $self->{+INPUT};
44 36         60 my $precision = $self->{+PRECISION};
45 36 100       83 if ( defined $precision) {
46 12         183 return sprintf "%.*f", $precision, $in;
47             }
48 24         46 my $tolerance = $self->{+TOLERANCE};
49 24         238 return "$in +/- $tolerance";
50             }
51              
52             sub operator {
53 17     17 1 230 my $self = shift;
54 17 100       60 return '' unless @_;
55 14         32 my ($got) = @_;
56              
57 14 100       46 return '' unless defined($got);
58 11 50 33     76 return '' unless length($got) && $got =~ m/\S/;
59              
60 11 100       32 if ( $self->{+PRECISION} )
61             {
62 1 50       4 return 'ne' if $self->{+NEGATE};
63 1         5 return 'eq';
64             }
65              
66 10 100       34 return '!=' if $self->{+NEGATE};
67 4         17 return '==';
68             }
69              
70             sub verify {
71 78     78 1 810 my $self = shift;
72 78         212 my %params = @_;
73 78         182 my ($got, $exists) = @params{qw/got exists/};
74              
75 78 100       183 return 0 unless $exists;
76 76 100       183 return 0 unless defined $got;
77 74 100       152 return 0 if ref $got;
78 72 100 100     594 return 0 unless length($got) && $got =~ m/\S/;
79              
80 70         169 my $input = $self->{+INPUT};
81 70         104 my $negate = $self->{+NEGATE};
82 70         117 my $tolerance = $self->{+TOLERANCE};
83 70         107 my $precision = $self->{+PRECISION};
84              
85 70         118 my @warnings;
86             my $out;
87             {
88 70     5   93 local $SIG{__WARN__} = sub { push @warnings => @_ };
  70         413  
  5         28  
89              
90 70         300 my $equal = ($input == $got);
91 70 100       154 if (!$equal) {
92 46 100       87 if (defined $tolerance) {
93 32 100 100     132 $equal = 1 if
94             $got > $input - $tolerance &&
95             $got < $input + $tolerance;
96             } else {
97 14         110 $equal =
98             sprintf("%.*f", $precision, $got) eq
99             sprintf("%.*f", $precision, $input);
100             }
101             }
102              
103 70 100       338 $out = $negate ? !$equal : $equal;
104             }
105              
106 70         173 for my $warn (@warnings) {
107 5 50       31 if ($warn =~ m/numeric/) {
108 5         10 $out = 0;
109 5         20 next; # This warning won't help anyone.
110             }
111 0         0 warn $warn;
112             }
113              
114 70         409 return $out;
115             }
116              
117             1;
118              
119             __END__