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. typical_case
  5. double_overflow
  6. double_underflow
  7. main

   1 #include <float.h>  // DBL_MAX, etc.
   2 #include <math.h>   // fabs()
   3 
   4 #include <glib.h>
   5 
   6 #include <crm_internal.h>
   7 
   8 // Ensure plenty of characters for %f display
   9 #define LOCAL_BUF_SIZE 2 * DBL_MAX_10_EXP
  10 
  11 /*
  12  * Avoids compiler warnings for floating-point equality checks.
  13  * Use for comparing numbers (e.g., 1.0 == 1.0), not expression values.
  14  */
  15 #define ASSERT_DBL_EQ(d1, d2) g_assert_cmpfloat(fabs(d1 - d2), \
  16                                                 <, DBL_EPSILON);
  17 
  18 static void
  19 empty_input_string(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  20 {
  21     double result;
  22 
  23     // Without default_text
  24     g_assert_cmpint(pcmk__scan_double(NULL, &result, NULL, NULL), ==, EINVAL);
  25     ASSERT_DBL_EQ(result, PCMK__PARSE_DBL_DEFAULT);
  26 
  27     g_assert_cmpint(pcmk__scan_double("", &result, NULL, NULL), ==, EINVAL);
  28     ASSERT_DBL_EQ(result, PCMK__PARSE_DBL_DEFAULT);
  29 
  30     // With default_text
  31     g_assert_cmpint(pcmk__scan_double(NULL, &result, "2.0", NULL), ==,
  32                     pcmk_rc_ok);
  33     ASSERT_DBL_EQ(result, 2.0);
  34 
  35     g_assert_cmpint(pcmk__scan_double("", &result, "2.0", NULL), ==, EINVAL);
  36     ASSERT_DBL_EQ(result, PCMK__PARSE_DBL_DEFAULT);
  37 }
  38 
  39 static void
  40 bad_input_string(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  41 {
  42     double result;
  43 
  44     // Without default text
  45     g_assert_cmpint(pcmk__scan_double("asdf", &result, NULL, NULL), ==, EINVAL);
  46     ASSERT_DBL_EQ(result, PCMK__PARSE_DBL_DEFAULT);
  47 
  48     g_assert_cmpint(pcmk__scan_double("as2.0", &result, NULL, NULL), ==,
  49                     EINVAL);
  50     ASSERT_DBL_EQ(result, PCMK__PARSE_DBL_DEFAULT);
  51 
  52     // With default text (not used)
  53     g_assert_cmpint(pcmk__scan_double("asdf", &result, "2.0", NULL), ==,
  54                     EINVAL);
  55     ASSERT_DBL_EQ(result, PCMK__PARSE_DBL_DEFAULT);
  56 
  57     g_assert_cmpint(pcmk__scan_double("as2.0", &result, "2.0", NULL), ==,
  58                     EINVAL);
  59     ASSERT_DBL_EQ(result, PCMK__PARSE_DBL_DEFAULT);
  60 }
  61 
  62 static void
  63 trailing_chars(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  64 {
  65     double result;
  66 
  67     g_assert_cmpint(pcmk__scan_double("2.0asdf", &result, NULL, NULL), ==,
  68                     pcmk_rc_ok);
  69     ASSERT_DBL_EQ(result, 2.0);
  70 }
  71 
  72 static void
  73 typical_case(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  74 {
  75     char str[LOCAL_BUF_SIZE];
  76     double result;
  77 
  78     g_assert_cmpint(pcmk__scan_double("0.0", &result, NULL, NULL), ==,
  79                     pcmk_rc_ok);
  80     ASSERT_DBL_EQ(result, 0.0);
  81 
  82     g_assert_cmpint(pcmk__scan_double("1.0", &result, NULL, NULL), ==,
  83                     pcmk_rc_ok);
  84     ASSERT_DBL_EQ(result, 1.0);
  85 
  86     g_assert_cmpint(pcmk__scan_double("-1.0", &result, NULL, NULL), ==,
  87                     pcmk_rc_ok);
  88     ASSERT_DBL_EQ(result, -1.0);
  89 
  90     snprintf(str, LOCAL_BUF_SIZE, "%f", DBL_MAX);
  91     g_assert_cmpint(pcmk__scan_double(str, &result, NULL, NULL), ==,
  92                     pcmk_rc_ok);
  93     ASSERT_DBL_EQ(result, DBL_MAX);
  94 
  95     snprintf(str, LOCAL_BUF_SIZE, "%f", -DBL_MAX);
  96     g_assert_cmpint(pcmk__scan_double(str, &result, NULL, NULL), ==,
  97                     pcmk_rc_ok);
  98     ASSERT_DBL_EQ(result, -DBL_MAX);
  99 }
 100 
 101 static void
 102 double_overflow(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 103 {
 104     char str[LOCAL_BUF_SIZE];
 105     double result;
 106 
 107     /*
 108      * 1e(DBL_MAX_10_EXP + 1) produces an inf value
 109      * Can't use ASSERT_DBL_EQ() because (inf - inf) == NaN
 110      */
 111     snprintf(str, LOCAL_BUF_SIZE, "1e%d", DBL_MAX_10_EXP + 1);
 112     g_assert_cmpint(pcmk__scan_double(str, &result, NULL, NULL), ==, EOVERFLOW);
 113     g_assert_cmpfloat(result, >, DBL_MAX);
 114 
 115     snprintf(str, LOCAL_BUF_SIZE, "-1e%d", DBL_MAX_10_EXP + 1);
 116     g_assert_cmpint(pcmk__scan_double(str, &result, NULL, NULL), ==, EOVERFLOW);
 117     g_assert_cmpfloat(result, <, -DBL_MAX);
 118 }
 119 
 120 static void
 121 double_underflow(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 122 {
 123     char str[LOCAL_BUF_SIZE];
 124     double result;
 125 
 126     /*
 127      * 1e(DBL_MIN_10_EXP - 1) produces a denormalized value (between 0
 128      * and DBL_MIN)
 129      *
 130      * C99/C11: result will be **no greater than** DBL_MIN
 131      */
 132     snprintf(str, LOCAL_BUF_SIZE, "1e%d", DBL_MIN_10_EXP - 1);
 133     g_assert_cmpint(pcmk__scan_double(str, &result, NULL, NULL), ==,
 134                     pcmk_rc_underflow);
 135     g_assert_cmpfloat(result, >=, 0.0);
 136     g_assert_cmpfloat(result, <=, DBL_MIN);
 137 
 138     snprintf(str, LOCAL_BUF_SIZE, "-1e%d", DBL_MIN_10_EXP - 1);
 139     g_assert_cmpint(pcmk__scan_double(str, &result, NULL, NULL), ==,
 140                     pcmk_rc_underflow);
 141     g_assert_cmpfloat(result, <=, 0.0);
 142     g_assert_cmpfloat(result, >=, -DBL_MIN);
 143 }
 144 
 145 int main(int argc, char **argv)
     /* [previous][next][first][last][top][bottom][index][help] */
 146 {
 147     g_test_init(&argc, &argv, NULL);
 148 
 149     // Test for input string issues
 150     g_test_add_func("/common/strings/double/empty_input", empty_input_string);
 151     g_test_add_func("/common/strings/double/bad_input", bad_input_string);
 152     g_test_add_func("/common/strings/double/trailing_chars", trailing_chars);
 153 
 154     // Test for numeric issues
 155     g_test_add_func("/common/strings/double/typical", typical_case);
 156     g_test_add_func("/common/strings/double/overflow", double_overflow);
 157     g_test_add_func("/common/strings/double/underflow", double_underflow);
 158 
 159     return g_test_run();
 160 }
 161 

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