root/lib/common/tests/strings/pcmk__scan_double_test.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. empty_input_string
  2. bad_input_string
  3. trailing_chars
  4. no_result_variable
  5. typical_case
  6. double_overflow
  7. double_underflow

   1 /*
   2  * Copyright 2004-2022 the Pacemaker project contributors
   3  *
   4  * The version control history for this file may have further details.
   5  *
   6  * This source code is licensed under the GNU General Public License version 2
   7  * or later (GPLv2+) WITHOUT ANY WARRANTY.
   8  */
   9 
  10 #include <crm_internal.h>
  11 
  12 #include <crm/common/unittest_internal.h>
  13 
  14 #include <float.h>  // DBL_MAX, etc.
  15 #include <math.h>   // fabs()
  16 
  17 // Ensure plenty of characters for %f display
  18 #define LOCAL_BUF_SIZE 2 * DBL_MAX_10_EXP
  19 
  20 /*
  21  * assert_float_equal doesn't exist for older versions of cmocka installed on some
  22  * of our builders, so define it in terms of regular assert() here in that case.
  23  */
  24 #if HAVE_DECL_ASSERT_FLOAT_EQUAL == 0
  25 #define assert_float_equal(a, b, epsilon) assert_true(fabs((a) - (b)) < (epsilon))
  26 #endif
  27 
  28 static void
  29 empty_input_string(void **state)
     /* [previous][next][first][last][top][bottom][index][help] */
  30 {
  31     double result;
  32 
  33     // Without default_text
  34     assert_int_equal(pcmk__scan_double(NULL, &result, NULL, NULL), EINVAL);
  35     assert_float_equal(result, PCMK__PARSE_DBL_DEFAULT, DBL_EPSILON);
  36 
  37     assert_int_equal(pcmk__scan_double("", &result, NULL, NULL), EINVAL);
  38     assert_float_equal(result, PCMK__PARSE_DBL_DEFAULT, DBL_EPSILON);
  39 
  40     // With default_text
  41     assert_int_equal(pcmk__scan_double(NULL, &result, "2.0", NULL), pcmk_rc_ok);
  42     assert_float_equal(result, 2.0, DBL_EPSILON);
  43 
  44     assert_int_equal(pcmk__scan_double("", &result, "2.0", NULL), EINVAL);
  45     assert_float_equal(result, PCMK__PARSE_DBL_DEFAULT, DBL_EPSILON);
  46 }
  47 
  48 static void
  49 bad_input_string(void **state)
     /* [previous][next][first][last][top][bottom][index][help] */
  50 {
  51     double result;
  52 
  53     // Without default text
  54     assert_int_equal(pcmk__scan_double("asdf", &result, NULL, NULL), EINVAL);
  55     assert_float_equal(result, PCMK__PARSE_DBL_DEFAULT, DBL_EPSILON);
  56 
  57     assert_int_equal(pcmk__scan_double("as2.0", &result, NULL, NULL), EINVAL);
  58     assert_float_equal(result, PCMK__PARSE_DBL_DEFAULT, DBL_EPSILON);
  59 
  60     // With default text (not used)
  61     assert_int_equal(pcmk__scan_double("asdf", &result, "2.0", NULL), EINVAL);
  62     assert_float_equal(result, PCMK__PARSE_DBL_DEFAULT, DBL_EPSILON);
  63 
  64     assert_int_equal(pcmk__scan_double("as2.0", &result, "2.0", NULL), EINVAL);
  65     assert_float_equal(result, PCMK__PARSE_DBL_DEFAULT, DBL_EPSILON);
  66 }
  67 
  68 static void
  69 trailing_chars(void **state)
     /* [previous][next][first][last][top][bottom][index][help] */
  70 {
  71     double result;
  72     char *end_text;
  73 
  74     assert_int_equal(pcmk__scan_double("2.0asdf", &result, NULL, &end_text), pcmk_rc_ok);
  75     assert_float_equal(result, 2.0, DBL_EPSILON);
  76     assert_string_equal(end_text, "asdf");
  77 }
  78 
  79 static void
  80 no_result_variable(void **state)
     /* [previous][next][first][last][top][bottom][index][help] */
  81 {
  82     pcmk__assert_asserts(pcmk__scan_double("asdf", NULL, NULL, NULL));
  83 }
  84 
  85 static void
  86 typical_case(void **state)
     /* [previous][next][first][last][top][bottom][index][help] */
  87 {
  88     char str[LOCAL_BUF_SIZE];
  89     double result;
  90 
  91     assert_int_equal(pcmk__scan_double("0.0", &result, NULL, NULL), pcmk_rc_ok);
  92     assert_float_equal(result, 0.0, DBL_EPSILON);
  93 
  94     assert_int_equal(pcmk__scan_double("1.0", &result, NULL, NULL), pcmk_rc_ok);
  95     assert_float_equal(result, 1.0, DBL_EPSILON);
  96 
  97     assert_int_equal(pcmk__scan_double("-1.0", &result, NULL, NULL), pcmk_rc_ok);
  98     assert_float_equal(result, -1.0, DBL_EPSILON);
  99 
 100     snprintf(str, LOCAL_BUF_SIZE, "%f", DBL_MAX);
 101     assert_int_equal(pcmk__scan_double(str, &result, NULL, NULL), pcmk_rc_ok);
 102     assert_float_equal(result, DBL_MAX, DBL_EPSILON);
 103 
 104     snprintf(str, LOCAL_BUF_SIZE, "%f", -DBL_MAX);
 105     assert_int_equal(pcmk__scan_double(str, &result, NULL, NULL), pcmk_rc_ok);
 106     assert_float_equal(result, -DBL_MAX, DBL_EPSILON);
 107 }
 108 
 109 static void
 110 double_overflow(void **state)
     /* [previous][next][first][last][top][bottom][index][help] */
 111 {
 112     char str[LOCAL_BUF_SIZE];
 113     double result;
 114 
 115     /*
 116      * 1e(DBL_MAX_10_EXP + 1) produces an inf value
 117      * Can't use assert_float_equal() because (inf - inf) == NaN
 118      */
 119     snprintf(str, LOCAL_BUF_SIZE, "1e%d", DBL_MAX_10_EXP + 1);
 120     assert_int_equal(pcmk__scan_double(str, &result, NULL, NULL), EOVERFLOW);
 121     assert_true(result > DBL_MAX);
 122 
 123     snprintf(str, LOCAL_BUF_SIZE, "-1e%d", DBL_MAX_10_EXP + 1);
 124     assert_int_equal(pcmk__scan_double(str, &result, NULL, NULL), EOVERFLOW);
 125     assert_true(result < -DBL_MAX);
 126 }
 127 
 128 static void
 129 double_underflow(void **state)
     /* [previous][next][first][last][top][bottom][index][help] */
 130 {
 131     char str[LOCAL_BUF_SIZE];
 132     double result;
 133 
 134     /*
 135      * 1e(DBL_MIN_10_EXP - 1) produces a denormalized value (between 0
 136      * and DBL_MIN)
 137      *
 138      * C99/C11: result will be **no greater than** DBL_MIN
 139      */
 140     snprintf(str, LOCAL_BUF_SIZE, "1e%d", DBL_MIN_10_EXP - 1);
 141     assert_int_equal(pcmk__scan_double(str, &result, NULL, NULL), pcmk_rc_underflow);
 142     assert_true(result >= 0.0);
 143     assert_true(result <= DBL_MIN);
 144 
 145     snprintf(str, LOCAL_BUF_SIZE, "-1e%d", DBL_MIN_10_EXP - 1);
 146     assert_int_equal(pcmk__scan_double(str, &result, NULL, NULL), pcmk_rc_underflow);
 147     assert_true(result <= 0.0);
 148     assert_true(result >= -DBL_MIN);
 149 }
 150 
 151 PCMK__UNIT_TEST(NULL, NULL,
 152                 cmocka_unit_test(empty_input_string),
 153                 cmocka_unit_test(bad_input_string),
 154                 cmocka_unit_test(trailing_chars),
 155                 cmocka_unit_test(no_result_variable),
 156                 cmocka_unit_test(typical_case),
 157                 cmocka_unit_test(double_overflow),
 158                 cmocka_unit_test(double_underflow))

/* [previous][next][first][last][top][bottom][index][help] */