[recipes] Add a test for number parsing



commit b85ca9ac6b5bef780971c3f83cd3f9f492768ee1
Author: Matthias Clasen <mclasen redhat com>
Date:   Fri Dec 23 18:15:40 2016 -0500

    Add a test for number parsing
    
    This already found quite a few irregularities, so yay for testing.

 tests/Makefile.am                  |   16 ++-
 tests/number-data/number1.expected |  396 ++++++++++++++++++++++++++++++++++++
 tests/number-data/number1.in       |   60 ++++++
 tests/number.c                     |  156 ++++++++++++++
 4 files changed, 626 insertions(+), 2 deletions(-)
---
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 41775ca..978af86 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -5,9 +5,13 @@ TESTS_ENVIRONMENT = \
        MALLOC_CHECK_=2                         \
        MALLOC_PERTURB_=$$(($${RANDOM:-256} % 256))
 
-TESTS = ingredients
+TESTS = \
+       number \
+       ingredients
 
-check_PROGRAMS = ingredients
+check_PROGRAMS = \
+       number \
+       ingredients
 
 ingredients_SOURCES = ingredients.c
 ingredients_CFLAGS = \
@@ -17,6 +21,14 @@ ingredients_CFLAGS = \
 
 ingredients_LDADD = $(RECIPES_LIBS)
 
+number_SOURCES = number.c
+number_CFLAGS = \
+       $(RECIPES_CFLAGS)       \
+       -DPKGDATADIR=\"$(pkgdatadir)\"  \
+       -I$(top_srcdir)/src
+
+number_LDADD = $(RECIPES_LIBS)
+
 EXTRA_DIST = \
        ingredients-data/valid-1.expected ingredients-data/valid-1.in   \
        ingredients-data/valid-2.expected ingredients-data/valid-2.in   \
diff --git a/tests/number-data/number1.expected b/tests/number-data/number1.expected
new file mode 100644
index 0000000..383bb22
--- /dev/null
+++ b/tests/number-data/number1.expected
@@ -0,0 +1,396 @@
+INPUT '123'
+REST ''
+FRACTION 1
+NUMERATOR 123
+DENOMINATOR 1
+VALUE 123
+FORMATTED '123'
+
+INPUT '123/201'
+REST ''
+FRACTION 1
+NUMERATOR 41
+DENOMINATOR 67
+VALUE 0.61194
+FORMATTED '41/67'
+
+INPUT '10.11'
+REST ''
+FRACTION 0
+NUMERATOR 0
+DENOMINATOR 0
+VALUE 10.11
+FORMATTED '10.11'
+
+INPUT '-0.001'
+REST ''
+FRACTION 0
+NUMERATOR 0
+DENOMINATOR 0
+VALUE -0.001
+FORMATTED '-0.001'
+
+INPUT '1/2'
+REST ''
+FRACTION 1
+NUMERATOR 1
+DENOMINATOR 2
+VALUE 0.5
+FORMATTED '½'
+
+INPUT '1/3'
+REST ''
+FRACTION 1
+NUMERATOR 1
+DENOMINATOR 3
+VALUE 0.333333
+FORMATTED '⅓'
+
+INPUT '2/6'
+REST ''
+FRACTION 1
+NUMERATOR 1
+DENOMINATOR 3
+VALUE 0.333333
+FORMATTED '⅓'
+
+INPUT '1/0'
+REST ''
+FRACTION 1
+NUMERATOR 1
+DENOMINATOR 0
+VALUE inf
+FORMATTED '1/0'
+
+INPUT '1/-1'
+REST ''
+FRACTION 1
+NUMERATOR -1
+DENOMINATOR 1
+VALUE -1
+FORMATTED '-1'
+
+INPUT '-3/-4'
+REST ''
+FRACTION 1
+NUMERATOR 3
+DENOMINATOR 4
+VALUE 0.75
+FORMATTED '¾'
+
+INPUT 'a dozen'
+REST ''
+FRACTION 1
+NUMERATOR 12
+DENOMINATOR 1
+VALUE 12
+FORMATTED '12'
+
+INPUT 'one'
+REST ''
+FRACTION 1
+NUMERATOR 1
+DENOMINATOR 1
+VALUE 1
+FORMATTED '1'
+
+INPUT 'two'
+REST ''
+FRACTION 1
+NUMERATOR 2
+DENOMINATOR 1
+VALUE 2
+FORMATTED '2'
+
+INPUT 'three'
+REST ''
+FRACTION 1
+NUMERATOR 3
+DENOMINATOR 1
+VALUE 3
+FORMATTED '3'
+
+INPUT 'four'
+REST ''
+FRACTION 1
+NUMERATOR 4
+DENOMINATOR 1
+VALUE 4
+FORMATTED '4'
+
+INPUT 'five'
+REST ''
+FRACTION 1
+NUMERATOR 5
+DENOMINATOR 1
+VALUE 5
+FORMATTED '5'
+
+INPUT 'six'
+REST ''
+FRACTION 1
+NUMERATOR 6
+DENOMINATOR 1
+VALUE 6
+FORMATTED '6'
+
+INPUT 'seven'
+REST ''
+FRACTION 1
+NUMERATOR 7
+DENOMINATOR 1
+VALUE 7
+FORMATTED '7'
+
+INPUT 'eight'
+REST ''
+FRACTION 1
+NUMERATOR 8
+DENOMINATOR 1
+VALUE 8
+FORMATTED '8'
+
+INPUT 'nine'
+REST ''
+FRACTION 1
+NUMERATOR 9
+DENOMINATOR 1
+VALUE 9
+FORMATTED '9'
+
+INPUT 'ten'
+REST ''
+FRACTION 1
+NUMERATOR 10
+DENOMINATOR 1
+VALUE 10
+FORMATTED '10'
+
+INPUT 'eleven'
+REST ''
+FRACTION 1
+NUMERATOR 11
+DENOMINATOR 1
+VALUE 11
+FORMATTED '11'
+
+INPUT 'twelve'
+REST ''
+FRACTION 1
+NUMERATOR 12
+DENOMINATOR 1
+VALUE 12
+FORMATTED '12'
+
+INPUT '¼'
+REST ''
+FRACTION 1
+NUMERATOR 1
+DENOMINATOR 4
+VALUE 0.25
+FORMATTED '¼'
+
+INPUT '½'
+REST ''
+FRACTION 1
+NUMERATOR 1
+DENOMINATOR 2
+VALUE 0.5
+FORMATTED '½'
+
+INPUT '¾'
+REST ''
+FRACTION 1
+NUMERATOR 3
+DENOMINATOR 4
+VALUE 0.75
+FORMATTED '¾'
+
+INPUT '⅐'
+REST ''
+FRACTION 1
+NUMERATOR 1
+DENOMINATOR 7
+VALUE 0.142857
+FORMATTED '⅐'
+
+INPUT '⅑'
+REST ''
+FRACTION 1
+NUMERATOR 1
+DENOMINATOR 9
+VALUE 0.111111
+FORMATTED '⅑'
+
+INPUT '⅒'
+REST ''
+FRACTION 1
+NUMERATOR 1
+DENOMINATOR 10
+VALUE 0.1
+FORMATTED '⅒'
+
+INPUT '⅓'
+REST ''
+FRACTION 1
+NUMERATOR 1
+DENOMINATOR 3
+VALUE 0.333333
+FORMATTED '⅓'
+
+INPUT '⅔'
+REST ''
+FRACTION 1
+NUMERATOR 2
+DENOMINATOR 3
+VALUE 0.666667
+FORMATTED '⅔'
+
+INPUT '⅕'
+REST ''
+FRACTION 1
+NUMERATOR 1
+DENOMINATOR 5
+VALUE 0.2
+FORMATTED '⅕'
+
+INPUT '⅖'
+REST ''
+FRACTION 1
+NUMERATOR 2
+DENOMINATOR 5
+VALUE 0.4
+FORMATTED '⅖'
+
+INPUT '⅗'
+REST ''
+FRACTION 1
+NUMERATOR 3
+DENOMINATOR 5
+VALUE 0.6
+FORMATTED '⅗'
+
+INPUT '⅘'
+REST ''
+FRACTION 1
+NUMERATOR 4
+DENOMINATOR 5
+VALUE 0.8
+FORMATTED '⅘'
+
+INPUT '⅙'
+REST ''
+FRACTION 1
+NUMERATOR 1
+DENOMINATOR 6
+VALUE 0.166667
+FORMATTED '⅙'
+
+INPUT '⅚'
+REST ''
+FRACTION 1
+NUMERATOR 5
+DENOMINATOR 6
+VALUE 0.833333
+FORMATTED '⅚'
+
+INPUT '⅛'
+REST ''
+FRACTION 1
+NUMERATOR 1
+DENOMINATOR 8
+VALUE 0.125
+FORMATTED '⅛'
+
+INPUT '⅜'
+REST ''
+FRACTION 1
+NUMERATOR 3
+DENOMINATOR 8
+VALUE 0.375
+FORMATTED '⅜'
+
+INPUT '⅝'
+REST ''
+FRACTION 1
+NUMERATOR 5
+DENOMINATOR 8
+VALUE 0.625
+FORMATTED '⅝'
+
+INPUT '⅞'
+REST ''
+FRACTION 1
+NUMERATOR 7
+DENOMINATOR 8
+VALUE 0.875
+FORMATTED '⅞'
+
+INPUT '1 1/2'
+REST ''
+FRACTION 1
+NUMERATOR 3
+DENOMINATOR 2
+VALUE 1.5
+FORMATTED '1 ½'
+
+INPUT '2 23/47'
+REST ''
+FRACTION 1
+NUMERATOR 117
+DENOMINATOR 47
+VALUE 2.48936
+FORMATTED '2 23/47'
+
+INPUT '1 ¼'
+REST ''
+FRACTION 1
+NUMERATOR 5
+DENOMINATOR 4
+VALUE 1.25
+FORMATTED '1 ¼'
+
+INPUT '2 ½'
+REST ''
+FRACTION 1
+NUMERATOR 5
+DENOMINATOR 2
+VALUE 2.5
+FORMATTED '2 ½'
+
+INPUT '1¼'
+REST ''
+FRACTION 1
+NUMERATOR 5
+DENOMINATOR 4
+VALUE 1.25
+FORMATTED '1 ¼'
+
+INPUT '2½'
+REST ''
+FRACTION 1
+NUMERATOR 5
+DENOMINATOR 2
+VALUE 2.5
+FORMATTED '2 ½'
+
+INPUT '10.11.12'
+REST '10.11.12'
+ERROR Could not parse 10.11.12 as a number
+
+INPUT '1/2/3'
+REST '1/2/3'
+ERROR Could not parse 1/2/3 as a number
+
+INPUT '--2'
+REST '--2'
+ERROR Could not parse --2 as a number
+
+INPUT '10 11.12'
+REST ' 11.12'
+FRACTION 0
+NUMERATOR 0
+DENOMINATOR 0
+VALUE 10
+FORMATTED '10'
+
diff --git a/tests/number-data/number1.in b/tests/number-data/number1.in
new file mode 100644
index 0000000..b8a34d0
--- /dev/null
+++ b/tests/number-data/number1.in
@@ -0,0 +1,60 @@
+# the following are all valid
+123
+123/201
+10.11
+-0.001
+1/2
+1/3
+2/6
+1/0
+1/-1
+-3/-4
+
+# number words we recognize
+a dozen
+one
+two
+three
+four
+five
+six
+seven
+eight
+nine
+ten
+eleven
+twelve
+
+# vulgar fractions
+¼
+½
+¾
+⅐
+⅑
+⅒
+⅓
+⅔
+⅕
+⅖
+⅗
+⅘
+⅙
+⅚
+⅛
+⅜
+⅝
+⅞
+
+# mixed numbers
+1 1/2
+2 23/47
+1 ¼
+2 ½
+1¼
+2½
+
+# now some invalid ones
+10.11.12
+1/2/3
+--2
+10 11.12
diff --git a/tests/number.c b/tests/number.c
new file mode 100644
index 0000000..c9775cc
--- /dev/null
+++ b/tests/number.c
@@ -0,0 +1,156 @@
+/* numbers.c
+ *
+ * Copyright (C) 2016 Matthias Clasen <mclasen redhat com#}#>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more &details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+#include <locale.h>
+#include <stdio.h>
+#include <glib.h>
+#include "gr-number.h"
+#include "gr-number.c"
+
+static GString *string;
+
+static void
+test_line (const char *line)
+{
+        GrNumber number;
+        char *input;
+        g_autoptr(GError) error = NULL;
+
+        g_string_append_printf (string, "INPUT '%s'\n", line);
+
+        input = (char *)line;
+        if (!gr_number_parse (&number, &input, &error)) {
+                g_string_append_printf (string, "REST '%s'\n", input);
+                g_string_append_printf (string, "ERROR %s\n", error->message);
+        }
+        else {
+                g_autofree char *formatted;
+
+                formatted = gr_number_format (&number);
+
+                g_string_append_printf (string, "REST '%s'\n", input);
+                g_string_append_printf (string, "FRACTION %d\n", number.fraction);
+                g_string_append_printf (string, "NUMERATOR %d\n", number.num);
+                g_string_append_printf (string, "DENOMINATOR %d\n", number.denom);
+                g_string_append_printf (string, "VALUE %g\n", number.value);
+                g_string_append_printf (string, "FORMATTED '%s'\n", formatted);
+        }
+
+        g_string_append (string, "\n");
+}
+
+static void
+test_file (const char *filename)
+{
+        g_autofree char *contents = NULL;
+        gsize length;
+        g_autoptr(GError) error = NULL;
+        g_auto(GStrv) lines = NULL;
+        int i;
+
+        if (!g_file_get_contents (filename, &contents, &length, &error)) {
+                fprintf (stderr, "%s\n", error->message);
+                return;
+        }
+
+        lines = g_strsplit (contents, "\n", -1);
+        for (i = 0; lines[i]; i++) {
+                if (lines[i][0] != 0 && lines[i][0] != '#')
+                        test_line (lines[i]);
+        }
+}
+
+static char *
+get_expected_filename (const char *filename)
+{
+        char *f, *p, *expected;
+
+        f = g_strdup (filename);
+        p = strstr (f, ".in");
+        if (p)
+                *p = 0;
+        expected = g_strconcat (f, ".expected", NULL);
+
+        g_free (f);
+
+        return expected;
+}
+
+static void
+test_parse (gconstpointer d)
+{
+        const char *filename = d;
+        char *expected_file;
+        char *expected;
+        GError *error = NULL;
+
+        expected_file = get_expected_filename (filename);
+
+        string = g_string_sized_new (0);
+
+        test_file (filename);
+
+        g_file_get_contents (expected_file, &expected, NULL, &error);
+        g_assert_no_error (error);
+        g_assert_cmpstr (string->str, ==, expected);
+        g_free (expected);
+
+        g_string_free (string, TRUE);
+
+        g_free (expected_file);
+}
+
+int main (int argc, char *argv[])
+{
+        GDir *dir;
+        GError *error;
+        const char *name;
+        char *path;
+
+        g_setenv ("LC_ALL", "en_US.UTF-8", TRUE);
+        setlocale (LC_ALL, "");
+
+        g_test_init (&argc, &argv, NULL);
+
+        /* allow to easily generate expected output for new test cases */
+        if (argc > 1) {
+                string = g_string_sized_new (0);
+                test_file (argv[1]);
+                g_print ("%s", string->str);
+                return 0;
+        }
+
+        error = NULL;
+        path = g_test_build_filename (G_TEST_DIST, "number-data", NULL);
+        dir = g_dir_open (path, 0, &error);
+        g_free (path);
+        g_assert_no_error (error);
+        while ((name = g_dir_read_name (dir)) != NULL) {
+                if (!g_str_has_suffix (name, ".in"))
+                        continue;
+
+                path = g_strdup_printf ("/number/parse/%s", name);
+                g_test_add_data_func_full (path, g_test_build_filename (G_TEST_DIST, "number-data", name, 
NULL),
+                                           test_parse, g_free);
+                g_free (path);
+        }
+        g_dir_close (dir);
+
+  return g_test_run ();
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]