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   1153 use strict;
  164         344  
  164         4965  
3 164     164   889 use warnings;
  164         491  
  164         4879  
4              
5 164     164   850 use Carp qw/confess/;
  164         333  
  164         7219  
6              
7 164     164   902 use base 'Test2::Compare::Base';
  164         388  
  164         21849  
8              
9             our $VERSION = '0.000155';
10              
11             our $DEFAULT_TOLERANCE = 1e-08;
12              
13 164     164   1258 use Test2::Util::HashBase qw/input tolerance precision/;
  164         382  
  164         1208  
14              
15             # Overloads '!' for us.
16 164     164   33812 use Test2::Compare::Negatable;
  164         365  
  164         1111  
17              
18             sub init {
19 28     28 0 977 my $self = shift;
20 28         130 my $input = $self->{+INPUT};
21              
22 28 100 100     169 if ( exists $self->{+TOLERANCE} and exists $self->{+PRECISION} ) {
    100 100        
23 1         179 confess "can't set both tolerance and precision";
24             } elsif (!exists $self->{+PRECISION} and !exists $self->{+TOLERANCE}) {
25 10         26 $self->{+TOLERANCE} = $DEFAULT_TOLERANCE
26             }
27              
28 27 100       330 confess "input must be defined for 'Float' check"
29             unless defined $input;
30              
31             # Check for ''
32 26 100 100     476 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     448 if exists $self->{+PRECISION} && $self->{+PRECISION} !~ m/^\d+$/;
37              
38 22         72 $self->SUPER::init(@_);
39             }
40              
41             sub name {
42 36     36 1 340 my $self = shift;
43 36         70 my $in = $self->{+INPUT};
44 36         58 my $precision = $self->{+PRECISION};
45 36 100       81 if ( defined $precision) {
46 12         199 return sprintf "%.*f", $precision, $in;
47             }
48 24         38 my $tolerance = $self->{+TOLERANCE};
49 24         230 return "$in +/- $tolerance";
50             }
51              
52             sub operator {
53 17     17 1 284 my $self = shift;
54 17 100       60 return '' unless @_;
55 14         28 my ($got) = @_;
56              
57 14 100       42 return '' unless defined($got);
58 11 50 33     77 return '' unless length($got) && $got =~ m/\S/;
59              
60 11 100       32 if ( $self->{+PRECISION} )
61             {
62 1 50       5 return 'ne' if $self->{+NEGATE};
63 1         5 return 'eq';
64             }
65              
66 10 100       33 return '!=' if $self->{+NEGATE};
67 4         16 return '==';
68             }
69              
70             sub verify {
71 78     78 1 803 my $self = shift;
72 78         211 my %params = @_;
73 78         175 my ($got, $exists) = @params{qw/got exists/};
74              
75 78 100       181 return 0 unless $exists;
76 76 100       161 return 0 unless defined $got;
77 74 100       163 return 0 if ref $got;
78 72 100 100     577 return 0 unless length($got) && $got =~ m/\S/;
79              
80 70         215 my $input = $self->{+INPUT};
81 70         148 my $negate = $self->{+NEGATE};
82 70         116 my $tolerance = $self->{+TOLERANCE};
83 70         109 my $precision = $self->{+PRECISION};
84              
85 70         160 my @warnings;
86             my $out;
87             {
88 70     5   93 local $SIG{__WARN__} = sub { push @warnings => @_ };
  70         438  
  5         31  
89              
90 70         276 my $equal = ($input == $got);
91 70 100       155 if (!$equal) {
92 46 100       95 if (defined $tolerance) {
93 32 100 100     127 $equal = 1 if
94             $got > $input - $tolerance &&
95             $got < $input + $tolerance;
96             } else {
97 14         102 $equal =
98             sprintf("%.*f", $precision, $got) eq
99             sprintf("%.*f", $precision, $input);
100             }
101             }
102              
103 70 100       337 $out = $negate ? !$equal : $equal;
104             }
105              
106 70         151 for my $warn (@warnings) {
107 5 50       28 if ($warn =~ m/numeric/) {
108 5         15 $out = 0;
109 5         11 next; # This warning won't help anyone.
110             }
111 0         0 warn $warn;
112             }
113              
114 70         564 return $out;
115             }
116              
117             1;
118              
119             __END__