diff --git a/ChangeLog b/ChangeLog index 826aa8480..474501e6b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2013-08-04 Stéphane Voltz + * sanei/sanei_constrain_value.c + testsuite/sanei/sanei_constrain_test.c: fixed the case where the + rounding in sanei_constrain_value computes a value higher than the + range maximum, spotted and proposed by viresh_shirol@yahoo.co.uk . + Added testcase for the bug in testsuite. + 2013-08-02 Stéphane Voltz * configure configure.in testsuite/Makefile.* testsuite/tools/*: add a testsuite for sane-desc, then merge hwdb support for sane-desc by diff --git a/sanei/sanei_constrain_value.c b/sanei/sanei_constrain_value.c index 451ec5501..8f601cc1a 100644 --- a/sanei/sanei_constrain_value.c +++ b/sanei/sanei_constrain_value.c @@ -219,6 +219,12 @@ sanei_constrain_value (const SANE_Option_Descriptor * opt, void *value, (unsigned int) (array[i] - range->min + range->quant / 2) / range->quant; v = v * range->quant + range->min; + /* due to rounding issues with sane 'fixed' values, + * the computed value may exceed max */ + if (v > range->max) + { + v = range->max; + } if (v != array[i]) { array[i] = v; diff --git a/testsuite/sanei/sanei_constrain_test.c b/testsuite/sanei/sanei_constrain_test.c index e0434ff76..0f66bbb5c 100644 --- a/testsuite/sanei/sanei_constrain_test.c +++ b/testsuite/sanei/sanei_constrain_test.c @@ -38,13 +38,20 @@ static SANE_Option_Descriptor none_bool_opt = { {NULL} }; -/* range for constraint */ +/* range for int constraint */ static const SANE_Range int_range = { 3, /* minimum */ 18, /* maximum */ 3 /* quantization */ }; +/* range for sane fixed constraint */ +static const SANE_Range fixed_range = { + SANE_FIX(1.0), /* minimum */ + SANE_FIX(431.8), /* maximum */ + SANE_FIX(0.01) /* quantization */ +}; + static SANE_Option_Descriptor int_opt = { SANE_NAME_SCAN_TL_X, SANE_TITLE_SCAN_TL_X, @@ -57,6 +64,18 @@ static SANE_Option_Descriptor int_opt = { {NULL} }; +static SANE_Option_Descriptor fixed_opt = { + SANE_NAME_SCAN_TL_X, + SANE_TITLE_SCAN_TL_X, + SANE_DESC_SCAN_TL_X, + SANE_TYPE_FIXED, + SANE_UNIT_MM, + sizeof (SANE_Word), + 0, + SANE_CONSTRAINT_RANGE, + {NULL} +}; + #define ARRAY_SIZE 7 static SANE_Option_Descriptor array_opt = { @@ -180,7 +199,7 @@ quant1_int_value (void) static void quant2_int_value (void) { - SANE_Int value = int_range.min + +int_range.quant - 1; + SANE_Int value = int_range.min + int_range.quant - 1; SANE_Word info = 0; SANE_Status status; @@ -222,6 +241,116 @@ above_max_int_value (void) assert (value == int_range.max); } +/* + * constrained fixed value + */ +static void +min_fixed_value (void) +{ + SANE_Int value = fixed_range.min; + SANE_Word info = 0; + SANE_Status status; + + status = sanei_constrain_value (&fixed_opt, &value, &info); + + /* check results */ + assert (status == SANE_STATUS_GOOD); + assert (info == 0); + assert (value == fixed_range.min); +} + +static void +max_fixed_value (void) +{ + SANE_Int value = fixed_range.max; + SANE_Word info = 0; + SANE_Status status; + + status = sanei_constrain_value (&fixed_opt, &value, &info); + + /* check results */ + assert (status == SANE_STATUS_GOOD); + assert (info == 0); + assert (value == fixed_range.max); +} + +static void +below_min_fixed_value (void) +{ + SANE_Int value = fixed_range.min - 1; + SANE_Word info = 0; + SANE_Status status; + + status = sanei_constrain_value (&fixed_opt, &value, &info); + + /* check results */ + assert (status == SANE_STATUS_GOOD); + assert (info == SANE_INFO_INEXACT); + assert (value == fixed_range.min); +} + +/* rounded to lower value */ +static void +quant1_fixed_value (void) +{ + SANE_Int value = fixed_range.min + fixed_range.quant/3; + SANE_Word info = 0; + SANE_Status status; + + status = sanei_constrain_value (&fixed_opt, &value, &info); + + /* check results */ + assert (status == SANE_STATUS_GOOD); + assert (info == SANE_INFO_INEXACT); + assert (value == fixed_range.min); +} + +/* rounded to higher value */ +static void +quant2_fixed_value (void) +{ + SANE_Int value = fixed_range.min + fixed_range.quant - fixed_range.quant/3; + SANE_Word info = 0; + SANE_Status status; + + status = sanei_constrain_value (&fixed_opt, &value, &info); + + /* check results */ + assert (status == SANE_STATUS_GOOD); + assert (info == SANE_INFO_INEXACT); + assert (value == fixed_range.min + fixed_range.quant); +} + +static void +in_range_fixed_value (void) +{ + SANE_Int value = fixed_range.min + fixed_range.quant; + SANE_Word info = 0; + SANE_Status status; + + status = sanei_constrain_value (&fixed_opt, &value, &info); + + /* check results */ + assert (status == SANE_STATUS_GOOD); + assert (info == 0); + assert (value == fixed_range.min + fixed_range.quant); +} + +static void +above_max_fixed_value (void) +{ + SANE_Int value = fixed_range.max + 1; + SANE_Word info = 0; + SANE_Status status; + + status = sanei_constrain_value (&fixed_opt, &value, &info); + + /* check results */ + assert (status == SANE_STATUS_GOOD); + assert (info == SANE_INFO_INEXACT); + assert (value == fixed_range.max); +} + static void above_max_word (void) @@ -599,6 +728,7 @@ sanei_constrain_suite (void) { /* to be compatible with pre-C99 compilers */ int_opt.constraint.range = &int_range; + fixed_opt.constraint.range = &fixed_range; array_opt.constraint.range = &int_range; word_array_opt.constraint.word_list = dpi_list; string_array_opt.constraint.string_list = string_list; @@ -612,6 +742,15 @@ sanei_constrain_suite (void) quant2_int_value (); in_range_int_value (); + /* tests for sane fixed constrained value */ + min_fixed_value (); + max_fixed_value (); + below_min_fixed_value (); + above_max_fixed_value (); + quant1_fixed_value (); + quant2_fixed_value (); + in_range_fixed_value (); + /* tests for constrained int array */ min_int_array (); max_int_array (); @@ -635,7 +774,7 @@ sanei_constrain_suite (void) string_array_ignorecase (); string_array_several (); - /* constraint non tests */ + /* constraint none tests */ none_int (); none_bool_nok (); none_bool_ok ();