On Tue, 18 Oct 2016, Gabriel F. T. Gomes wrote:
> +/* Hexadecimal tests. */
> +static const struct htests htest[] = {
> + {"%a", { "0x1,ffp+6", "0x3,fep+5", "0x7,fcp+4", "0xf,f8p+3" },
> + {0x1.ffp+6, 0x1.ffp+6, 0x1.ffp+6}},
> + {"%a", { "0x1,88p+4", "0x3,1p+3", "0x6,2p+2", "0xc,4p+1" },
> + {0x1.88p+4, 0x1.88p+4, 0x1.88p+4}},
> + {"%A", { "-0X1,88P+5", "-0X3,1P+4", "-0X6,2P+3", "-0XC,4P+2" },
> + {-0x1.88p+5, -0x1.88p+5, -0x1.88p+5}},
> + {"%a", { "0x1,44p+10", "0x2,88p+9", "0x5,1p+8", "0xa,2p+7"},
> + {0x1.44p+10, 0x1.44p+10, 0x1.44p+10}},
> + {"%a", { "0x1p-10", "0x2p-11", "0x4p-12", "0x8p-13"},
> + {0x0.0040p+0, 0x0.0040p+0, 0x0.0040p+0}},
> + {"%a", { "0x1,4p+3", "0x2,8p+2", "0x5p+1", "0xap+0"},
> + {10.0, 10.0, 10.0}}
> +};
These still aren't type-generic.
> +/* Hexadecimal tests. */
> +static const struct htests htest[] = {
> + {"%a", { "0x1.ffp+6", "0x3.fep+5", "0x7.fcp+4", "0xf.f8p+3" },
> + {0x1.ffp+6, 0x1.ffp+6, 0x1.ffp+6}},
> + {"%a", { "0x1.88p+4", "0x3.1p+3", "0x6.2p+2", "0xc.4p+1" },
> + {0x1.88p+4, 0x1.88p+4, 0x1.88p+4}},
> + {"%A", { "-0X1.88P+5", "-0X3.1P+4", "-0X6.2P+3", "-0XC.4P+2" },
> + {-0x1.88p+5, -0x1.88p+5, -0x1.88p+5}},
> + {"%a", { "0x1.44p+10", "0x2.88p+9", "0x5.1p+8", "0xa.2p+7"},
> + {0x1.44p+10, 0x1.44p+10, 0x1.44p+10}},
> + {"%a", { "0x1p-10", "0x2p-11", "0x4p-12", "0x8p-13"},
> + {0x0.0040p+0, 0x0.0040p+0, 0x0.0040p+0}},
> + {"%a", { "0x1.4p+3", "0x2.8p+2", "0x5p+1", "0xap+0"},
> + {10.0, 10.0, 10.0}}
Likewise.
> +#define TEST(s, fmt, size, rc, f, d, ld) \
> + { \
> + s, fmt, size, rc, { ENTRY (f, d, ld) } \
> + }
You should have one argument to TEST that is the constant used for all
types (and that then gets the appropriate suffix added to it for each
type). It should not be necessary to update the tables of tests at all
when adding a new floating-point type (in general, the idea of making such
tests type-generic is so that as little as possible needs to change to
make them test a new type; ideally only the definitions of
GEN_TEST_STRTOD_FOREACH and STRTOD_TEST_FOREACH). The only obvious
differences I see between the constants in your tests for different types
is that some have more precision in the constants for double and long
double, but it's fine to have the extra digits in the float constant even
if they aren't significant to its value.
That is, the definition should look something like
{ s, fmt, size, rc, { GEN_TEST_STRTOD_FOREACH (SOMETHING, f) } }
where SOMETHING expands to concatenate its 7th argument (the
floating-point number) with its 5th (the constant suffix) (followed by a
comma). Then I think you can get rid of the ENTRY and CHOOSE macros.
(tst-strtod-round is different because it involves data for every
floating-point *format*, which then needs mapping to the supported types.)
@@ -79,7 +79,7 @@ tests := tst-strtol tst-strtod testmb testrand testsort testdiv \
tst-setcontext3 tst-tls-atexit-nodelete \
tst-strtol-locale tst-strtod-nan-locale tst-strfmon_l \
tst-quick_exit tst-thread-quick_exit tst-width \
- tst-width-stdint
+ tst-width-stdint tst-strfrom tst-strfrom-locale
tests-static := tst-secure-getenv
ifeq ($(have-cxx-thread_local),yes)
CFLAGS-tst-quick_exit.o = -std=c++11
@@ -158,6 +158,8 @@ $(objpfx)tst-strtod5.out: $(gen-locales)
$(objpfx)tst-strtol-locale.out: $(gen-locales)
$(objpfx)tst-strtod-nan-locale.out: $(gen-locales)
$(objpfx)tst-strfmon_l.out: $(gen-locales)
+$(objpfx)tst-strfrom.out: $(gen-locales)
+$(objpfx)tst-strfrom-locale.out: $(gen-locales)
endif
# Testdir has to be named stdlib and needs to be writable
new file mode 100644
@@ -0,0 +1,115 @@
+/* Tests for strfromf, strfromd, strfroml functions.
+ Copyright (C) 2016 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "tst-strfrom.h"
+
+static const struct test tests[] = {
+ TEST ("12,345000", "%f", 50, 9,
+ 12.345, 12.345, 12.345),
+ TEST ("9,999", "%.3f", 50, 5,
+ 9.999, 9.999, 9.999),
+ TEST ("0,125000", "%f", 50, 8,
+ .125, .125, .125),
+ TEST ("0,000000", "%f", 50, 8,
+ .0, .0, .0),
+ TEST ("0", "%g", 50, 1,
+ .0, .0, .0),
+ TEST ("9,900000", "%f", 50, 8,
+ 9.9, 9.9, 9.9),
+ TEST ("9,1", "%.5f", 4, 7,
+ 9.123456, 9.123456, 9.123456),
+ TEST ("9,91235", "%g", 50, 7,
+ 9.9123456, 9.91234567812345678, 9.91234567812345678),
+ TEST ("79,8765", "%G", 50, 7,
+ 79.876543, 79.8765432111, 79.8765432111),
+ TEST ("79,9", "%.3g", 50, 4,
+ 79.876543, 79.8765432111, 79.8765432111),
+ TEST ("1,000000e+38", "%e", 50, 12,
+ 1e+38, 1e+38, 1e+38),
+ TEST ("1,000000e+38", "%e", 50, 12,
+ 1e38, 1e38, 1e38),
+ TEST ("-1,000000e-37", "%e", 50, 13,
+ -1e-37, -1e-37, -1e-37),
+ TEST ("1,000000e-37", "%e", 50, 12,
+ 0.00000001e-29, 0.00000001e-29, 0.00000001e-29),
+ TEST ("1,000000e-37", "%e", 50, 12,
+ 1.000000e-37, 1.000000e-37, 1.000000e-37),
+ TEST ("5,900000e-16", "%e", 50, 12,
+ 5.9e-16, 5.9e-16, 5.9e-16),
+ TEST ("1,234500e+20", "%e", 50, 12,
+ 12.345e19, 12.345e19, 12.345e19),
+ TEST ("1,000000e+05", "%e", 50, 12,
+ 1e5, 1e5, 1e5),
+ TEST ("-NAN", "%G", 50, 4,
+ -NAN_, -NAN_, -NAN_),
+ TEST ("-inf", "%g", 50, 4,
+ -INF, -INF, -INF),
+ TEST ("inf", "%g", 50, 3,
+ INF, INF, INF)
+ };
+/* Tests with buffer size small. */
+static const struct test stest[] = {
+ TEST ("1234", "%g", 5, 7,
+ 12345.345, 12345.345, 12345.345),
+ TEST ("0,12", "%f", 5, 8,
+ .125, .125, .125),
+ TEST ("9,99", "%.3f", 5, 5,
+ 9.999, 9.999, 9.999),
+ TEST ("100", "%g", 5, 3,
+ 1e2, 1e2, 1e2)
+};
+/* Hexadecimal tests. */
+static const struct htests htest[] = {
+ {"%a", { "0x1,ffp+6", "0x3,fep+5", "0x7,fcp+4", "0xf,f8p+3" },
+ {0x1.ffp+6, 0x1.ffp+6, 0x1.ffp+6}},
+ {"%a", { "0x1,88p+4", "0x3,1p+3", "0x6,2p+2", "0xc,4p+1" },
+ {0x1.88p+4, 0x1.88p+4, 0x1.88p+4}},
+ {"%A", { "-0X1,88P+5", "-0X3,1P+4", "-0X6,2P+3", "-0XC,4P+2" },
+ {-0x1.88p+5, -0x1.88p+5, -0x1.88p+5}},
+ {"%a", { "0x1,44p+10", "0x2,88p+9", "0x5,1p+8", "0xa,2p+7"},
+ {0x1.44p+10, 0x1.44p+10, 0x1.44p+10}},
+ {"%a", { "0x1p-10", "0x2p-11", "0x4p-12", "0x8p-13"},
+ {0x0.0040p+0, 0x0.0040p+0, 0x0.0040p+0}},
+ {"%a", { "0x1,4p+3", "0x2,8p+2", "0x5p+1", "0xap+0"},
+ {10.0, 10.0, 10.0}}
+};
+GEN_TEST_STRTOD_FOREACH (TEST_STRFROM)
+
+static int
+test_locale (const char *locale)
+{
+ printf ("Testing in locale: %s\n", locale);
+ if (setlocale (LC_ALL, locale) == NULL)
+ {
+ printf ("Cannot set locale %s\n", locale);
+ }
+ return STRTOD_TEST_FOREACH (test_);
+}
+
+static int
+do_test (void)
+{
+ int result = 0;
+ result += test_locale ("de_DE.UTF-8");
+ result += test_locale ("tr_TR.ISO-8859-9");
+ result += test_locale ("tr_TR.UTF-8");
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
new file mode 100644
@@ -0,0 +1,116 @@
+/* Tests for strfromf, strfromd, strfroml functions.
+ Copyright (C) 2016 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "tst-strfrom.h"
+
+static const struct test tests[] = {
+ TEST ("12.345000", "%f", 50, 9,
+ 12.345, 12.345, 12.345),
+ TEST ("9.999", "%.3f", 50, 5,
+ 9.999, 9.999, 9.999),
+ TEST ("0.125000", "%f", 50, 8,
+ .125, .125, .125),
+ TEST ("0.000000", "%f", 50, 8,
+ .0, .0, .0),
+ TEST ("0", "%g", 50, 1,
+ .0, .0, .0),
+ TEST ("9.900000", "%f", 50, 8,
+ 9.9, 9.9, 9.9),
+ TEST ("9.1", "%.5f", 4, 7,
+ 9.123456, 9.123456, 9.123456),
+ TEST ("9.91235", "%g", 50, 7,
+ 9.9123456, 9.91234567812345678, 9.91234567812345678),
+ TEST ("79.8765", "%G", 50, 7,
+ 79.876543, 79.8765432111, 79.8765432111),
+ TEST ("79.9", "%.3g", 50, 4,
+ 79.876543, 79.8765432111, 79.8765432111),
+ TEST ("1.000000e+38", "%e", 50, 12,
+ 1e+38, 1e+38, 1e+38),
+ TEST ("1.000000e+38", "%e", 50, 12,
+ 1e38, 1e38, 1e38),
+ TEST ("-1.000000e-37", "%e", 50, 13,
+ -1e-37, -1e-37, -1e-37),
+ TEST ("1.000000e-37", "%e", 50, 12,
+ 0.00000001e-29, 0.00000001e-29, 0.00000001e-29),
+ TEST ("1.000000e-37", "%e", 50, 12,
+ 1.000000e-37, 1.000000e-37, 1.000000e-37),
+ TEST ("5.900000e-16", "%e", 50, 12,
+ 5.9e-16, 5.9e-16, 5.9e-16),
+ TEST ("1.234500e+20", "%e", 50, 12,
+ 12.345e19, 12.345e19, 12.345e19),
+ TEST ("1.000000e+05", "%e", 50, 12,
+ 1e5, 1e5, 1e5),
+ TEST ("-NAN", "%G", 50, 4,
+ -NAN_, -NAN_, -NAN_),
+ TEST ("-inf", "%g", 50, 4,
+ -INF, -INF, -INF),
+ TEST ("inf", "%g", 50, 3,
+ INF, INF, INF)
+ };
+
+/* Tests with buffer size small. */
+static const struct test stest[] = {
+ TEST ("1234", "%g", 5, 7,
+ 12345.345, 12345.345, 12345.345),
+ TEST ("0.12", "%f", 5, 8,
+ .125, .125, .125),
+ TEST ("9.99", "%.3f", 5, 5,
+ 9.999, 9.999, 9.999),
+ TEST ("100", "%g", 5, 3,
+ 1e2, 1e2, 1e2)
+};
+/* Hexadecimal tests. */
+static const struct htests htest[] = {
+ {"%a", { "0x1.ffp+6", "0x3.fep+5", "0x7.fcp+4", "0xf.f8p+3" },
+ {0x1.ffp+6, 0x1.ffp+6, 0x1.ffp+6}},
+ {"%a", { "0x1.88p+4", "0x3.1p+3", "0x6.2p+2", "0xc.4p+1" },
+ {0x1.88p+4, 0x1.88p+4, 0x1.88p+4}},
+ {"%A", { "-0X1.88P+5", "-0X3.1P+4", "-0X6.2P+3", "-0XC.4P+2" },
+ {-0x1.88p+5, -0x1.88p+5, -0x1.88p+5}},
+ {"%a", { "0x1.44p+10", "0x2.88p+9", "0x5.1p+8", "0xa.2p+7"},
+ {0x1.44p+10, 0x1.44p+10, 0x1.44p+10}},
+ {"%a", { "0x1p-10", "0x2p-11", "0x4p-12", "0x8p-13"},
+ {0x0.0040p+0, 0x0.0040p+0, 0x0.0040p+0}},
+ {"%a", { "0x1.4p+3", "0x2.8p+2", "0x5p+1", "0xap+0"},
+ {10.0, 10.0, 10.0}}
+};
+GEN_TEST_STRTOD_FOREACH (TEST_STRFROM)
+
+static int
+test_locale (const char *locale)
+{
+ printf ("Testing in locale: %s\n", locale);
+ if (setlocale (LC_ALL, locale) == NULL)
+ {
+ printf ("Cannot set locale %s\n", locale);
+ }
+ return STRTOD_TEST_FOREACH (test_);
+}
+
+static int
+do_test (void)
+{
+ int result = 0;
+ result += test_locale ("C");
+ result += test_locale ("en_US.ISO-8859-1");
+ result += test_locale ("en_US.UTF-8");
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
new file mode 100644
@@ -0,0 +1,126 @@
+/* Tests for strfromf, strfromd, strfroml functions.
+ Copyright (C) 2016 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <float.h>
+#include <math.h>
+#include <locale.h>
+
+#include "tst-strtod.h"
+
+#define _CONCAT(a, b) a ## b
+#define CONCAT(a, b) _CONCAT (a, b)
+
+/* Generator to create an FTYPE member variabled named FSUF
+ * used to populate struct member variables. */
+#define FTYPE_MEMBER(FSUF, FTYPE, FTOSTR, LSUF, CSUF) \
+ FTYPE FSUF;
+
+#define STRUCT_FOREACH_FLOAT_FTYPE GEN_TEST_STRTOD_FOREACH (FTYPE_MEMBER)
+
+/* Add type specific choosing macros below. */
+#define CHOOSE_f(f,...) f
+#define CHOOSE_d(f,d,...) d
+#define CHOOSE_ld(f,d,ld...) ld
+
+/* Selector for expected result field of a given type. */
+#define _ENTRY(FSUF, FTYPE, FTOSTR, LSUF, CSUF, ...) \
+ CONCAT (CHOOSE_ ## FSUF (__VA_ARGS__), LSUF),
+#define ENTRY(...) \
+ GEN_TEST_STRTOD_FOREACH (_ENTRY, __VA_ARGS__)
+
+/* This is hacky way around the seemingly unavoidable macro
+ * expansion of the INFINITY or HUGE_VAL like macros in the
+ * above. It is assumed the compiler will implicitly convert
+ * the infinity correctly. */
+#define INF INFINITY + 0.0
+#define NAN_ NAN + 0.0
+
+struct test_input
+{
+ STRUCT_FOREACH_FLOAT_FTYPE
+};
+struct test {
+ const char *s;
+ const char *fmt;
+ int size;
+ int rc;
+ struct test_input t;
+};
+
+#define TEST(s, fmt, size, rc, f, d, ld) \
+ { \
+ s, fmt, size, rc, { ENTRY (f, d, ld) } \
+ }
+/* Hexadecimal tests. */
+struct htests
+{
+ const char *fmt;
+ const char *exp[4];
+ struct test_input t;
+};
+
+#define TEST_STRFROM(FSUF, FTYPE, FTOSTR, LSUF, CSUF) \
+static int \
+test_ ## FSUF (void) \
+{ \
+ char buf[50], sbuf[5]; \
+ int status = 0; \
+ int i, rc = 0, rc1 = 0; \
+ for (i = 0; i < sizeof (stest) / sizeof (stest[0]); i++) \
+ { \
+ rc = FTOSTR (sbuf, stest[i].size, stest[i].fmt, stest[i].t.FSUF); \
+ rc1 = (strcmp (sbuf, stest[i].s) != 0) || (rc != stest[i].rc); \
+ if (rc1) \
+ { \
+ printf (#FTOSTR ": got %s (%d), expected %s (%d)\n", \
+ sbuf, rc, stest[i].s, stest[i].rc); \
+ status++; \
+ } \
+ } \
+ for (i = 0; i < sizeof (tests) / sizeof (tests[0]); i++) \
+ { \
+ rc = FTOSTR (buf, tests[i].size, tests[i].fmt, tests[i].t.FSUF); \
+ rc1 = (strcmp (buf, tests[i].s) != 0) || (rc != tests[i].rc); \
+ if (rc1) \
+ { \
+ printf (#FTOSTR ": got %s (%d), expected %s (%d)\n", \
+ buf, rc, tests[i].s, tests[i].rc); \
+ status++; \
+ } \
+ } \
+ for (i = 0; i < sizeof (htest) / sizeof (htest[0]); i++) \
+ { \
+ rc = FTOSTR (buf, 50, htest[i].fmt, htest[i].t.FSUF); \
+ if (strcmp (buf, htest[i].exp[0]) == 0 || \
+ strcmp (buf, htest[i].exp[1]) == 0 || \
+ strcmp (buf, htest[i].exp[2]) == 0 || \
+ strcmp (buf, htest[i].exp[3]) == 0) \
+ continue; \
+ else \
+ { \
+ printf (#FTOSTR ": got %s (%d), expected %s or %s or %s " \
+ "or %s\n", buf, rc, htest[i].exp[0], htest[i].exp[1], \
+ htest[i].exp[2], htest[i].exp[3]); \
+ status++; \
+ } \
+ } \
+ return status; \
+}