From b310ee60fa351d6ea736324a22aa5864f854215d Mon Sep 17 00:00:00 2001 From: Ryan Jendoubi Date: Tue, 17 Jul 2012 21:07:55 +0100 Subject: [PATCH] Some headway to testing float types in Simple.t However, still a long way to go; don't want to get bogged down in this aspect any longer. modified: Makefile.PL modified: t/Simple.t --- Makefile.PL | 6 ++++-- t/Simple.t | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 60 insertions(+), 12 deletions(-) diff --git a/Makefile.PL b/Makefile.PL index 097aba2..3f45d68 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -70,6 +70,7 @@ WriteMakefile( ABSTRACT_FROM => 'lib/Ctypes.pm', AUTHOR => 'Ryan Jendoubi {}, + BUILD_REQUIRES => {"Regexp::Common" => 0}, LIBS => $libdir ? [ "-L$libdir -lffi" ] : [ "-lffi" ], INC => $incdir ? "-I. -I$incdir" : "-I.", realclean => {FILES => "Ctypes_float_minima.h"}, @@ -218,8 +219,9 @@ if (eval {require ExtUtils::Constant; 1}) { PERL_USHORT_MAX PERL_INT_MIN PERL_INT_MAX PERL_UINT_MIN PERL_UINT_MAX PERL_LONG_MIN PERL_LONG_MAX PERL_ULONG_MIN PERL_ULONG_MAX PERL_UCHAR_MIN PERL_UCHAR_MAX CHAR_MIN CHAR_MAX - FLT_MAX CTYPES_FLT_MIN DBL_MAX CTYPES_DBL_MIN - LDBL_MAX CTYPES_LDBL_MIN|, + FLT_MAX CTYPES_FLT_MIN FLT_EPSILON + DBL_MAX CTYPES_DBL_MIN DBL_EPSILON + LDBL_MAX CTYPES_LDBL_MIN LDBL_EPSILON|, {name=>"FFI_BAD_ABI", macro=>"1"}, {name=>"FFI_BAD_TYPEDEF", macro=>"1"}, {name=>"FFI_OK", macro=>"1"}); diff --git a/t/Simple.t b/t/Simple.t index d758399..6559d3b 100644 --- a/t/Simple.t +++ b/t/Simple.t @@ -6,6 +6,9 @@ use Carp; BEGIN { use_ok( Ctypes ) } use Ctypes::Util qw|create_range|; +use Math::BigFloat; +use Regexp::Common; + # # Takes a hash of properties of Simple types @@ -55,12 +58,14 @@ sub SimpleTest { # What does this type return? - my( $ret_input, $ret_char, $ret_num, $is_float ); + my( $ret_input, $ret_char, $ret_num, $is_float, $epsilon ); $ret_input = $typehash->{ret_input} if exists $typehash->{ret_input}; $ret_char = $typehash->{ret_char} if exists $typehash->{ret_char}; $ret_num = $typehash->{ret_num} if exists $typehash->{ret_num}; + $epsilon = $typehash->{epsilon} if exists $typehash->{epsilon}; + my $ret_check = $ret_input ? 1 : 0 + $ret_char ? 1 : 0 + @@ -78,10 +83,14 @@ sub SimpleTest { diag "is float: $is_float\n" if $Ctypes::Type::Simple::Debug; + $epsilon = 1 unless $epsilon; + my $get_return = sub { my $input = shift; if( $ret_input ) { - if( Ctypes::Type::is_a_number($input) ){ + if( Ctypes::Type::is_a_number($input) + or ( ref($input) eq 'Math::BigInt' ) + or ( ref($input) eq 'Math::BigFloat' ) ) { unless( $is_float ) { return int( $input ); } else { @@ -92,14 +101,18 @@ sub SimpleTest { } } if( $ret_char ) { - if( Ctypes::Type::is_a_number($input) ){ + if( Ctypes::Type::is_a_number($input) + or ( ref($input) eq 'Math::BigInt' ) + or ( ref($input) eq 'Math::BigFloat' ) ) { return chr($input); } else { return substr($input, 0, 1); } } if( $ret_num ) { - if( Ctypes::Type::is_a_number($input) ) { + if( Ctypes::Type::is_a_number($input) + or ( ref($input) eq 'Math::BigInt' ) + or ( ref($input) eq 'Math::BigFloat' ) ) { unless( $is_float ) { return int( $input ); } else { @@ -141,7 +154,7 @@ sub SimpleTest { like( $@, qr/$name: cannot take references \(got ARRAY.*\)/ ); }; - unless( $is_float ) { + unless( $is_float == 1 ) { subtest "$name drops numbers after decimal point" => sub { plan tests => 3; $input = 95.2; @@ -156,20 +169,33 @@ sub SimpleTest { # so these tests can't really be any better. # **reference to the standard? subtest "$name: number overflow" => sub { - for( $range->( $MIN - $extra, $MIN - 1 ) ) { + for( $range->( $MIN - $extra, $MIN - $epsilon ) ) { warnings_exist { $$x = $_ } - [ { carped => qr/$name: numeric values must be integers $MIN <= x <= $MAX \(got $_\)/} ]; + [ { carped => qr/ + $name:\ numeric\ values\ must\ be + \ (integers\ )? $RE{num}{real} + \ <=\ x\ <=\ $RE{num}{real} + \ \(got\ $RE{num}{real}\) + /x } ]; isnt( $$x, $get_return->($_) ); ok( $$x >= $MIN ); } for( $range->( $MIN, $MAX, $cover, $weight, $want_int ) ) { $$x = $_; + SKIP: { + skip "Todo: make this work for floats", 1 if $is_float; is( $$x, $get_return->($_) ); + } is( ${$x->data}, pack($x->packcode, $_ ) ); } for( $range->( $MAX + 1, $MAX + $extra ) ) { warnings_exist { $$x = $_ } - [ { carped => qr/$name: numeric values must be integers $MIN <= x <= $MAX \(got $_\)/} ]; + [ { carped => qr/ + $name:\ numeric\ values\ must\ be + \ (integers\ )? $RE{num}{real} + \ <=\ x\ <=\ $RE{num}{real} + \ \(got\ $RE{num}{real}\) + /x } ]; isnt( $$x, $get_return->($_) ); ok( $$x <= $MAX ); } @@ -542,8 +568,28 @@ my $types = [ weight => 1, want_int => 1, }, +# TODO: Various problems with testing float types +# { #10 +# instantiator => 'c_float', +# packcode => 'f', +# sizecode => 'f', +# typecode => 'f', +# name => 'c_float', +# MAX => Math::BigFloat->new( (Ctypes::constant('FLT_MAX'))[1] ), +# MIN => Math::BigFloat->new( (Ctypes::constant('CTYPES_FLT_MIN'))[1] ), +# epsilon => Math::BigFloat->new( (Ctypes::constant('FLT_EPSILON'))[1] ), +# +# is_signed => 1, +# is_float => 1, +# # For test value range: +# extra => 10, +# cover => 100, +# weight => 1, +# want_int => 0, +# }, ]; -SimpleTest($_) for ( @$types ); # [ $#types ]; - +# Comment as appropriate +# SimpleTest( $types->[9] ); # convenient testing of new type +SimpleTest($_) for ( @$types ); # testing all types done_testing(); -- 2.1.4