[v2] Make __strtod_internal tests type-generic
Checks
Context |
Check |
Description |
redhat-pt-bot/TryBot-apply_patch |
success
|
Patch applied to master at the time it was sent
|
linaro-tcwg-bot/tcwg_glibc_build--master-aarch64 |
success
|
Build passed
|
redhat-pt-bot/TryBot-32bit |
success
|
Build for i686
|
linaro-tcwg-bot/tcwg_glibc_check--master-aarch64 |
success
|
Test passed
|
linaro-tcwg-bot/tcwg_glibc_build--master-arm |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_glibc_check--master-arm |
success
|
Test passed
|
Commit Message
Make __strtod_internal tests type-generic
Some of the strtod tests use type-generic machinery in tst-strtod.h to
test the strto* functions for all floating types, while others only
test double even when the tests are in fact meaningful for all
floating types.
Convert the tests of the internal __strtod_internal interface to cover
all floating types. I haven't tried to convert them to use newer test
interfaces in other ways, just made the changes necessary to use the
type-generic machinery. As an internal interface, there are no
aliases for different types with the same ABI (however,
__strtold_internal is defined even if long double has the same ABI as
double), so macros used by the type-generic testing code are redefined
as needed to avoid expecting such aliases to be present.
Tested for x86_64.
---
Changed in v2: define _LIBC_TEST in strtod5i.c to ensure copysignl is
declared on platforms where long double has the same ABI as double (as
an internal test, the rules about not declaring such aliases apply by
default), shown to be needed by CI on Arm.
Comments
Ping. This patch
<https://sourceware.org/pipermail/libc-alpha/2024-August/159203.html> is
pending review.
A few typos but otherwise OK. One of the test looks locale-dependent
but "it worked before".
Reviewed-by: DJ Delorie <dj@redhat.com>
Joseph Myers <josmyers@redhat.com> writes:
> diff --git a/stdlib/tst-strtod1i.c b/stdlib/tst-strtod1i.c
> index 9d6bb760fb..dec1ef37c1 100644
> --- a/stdlib/tst-strtod1i.c
> +++ b/stdlib/tst-strtod1i.c
> @@ -25,60 +25,91 @@
> #include <string.h>
> #include <math.h>
>
> -/* Perform a few tests in a locale with thousands separators. */
> -static int
> -do_test (void)
> -{
> - static const struct
> - {
> - const char *loc;
> - const char *str;
> - double exp;
> - ptrdiff_t nread;
> - } tests[] =
> - {
> - { "de_DE.UTF-8", "1,5", 1.5, 3 },
> - { "de_DE.UTF-8", "1.5", 1.0, 1 },
> - { "de_DE.UTF-8", "1.500", 1500.0, 5 },
> - { "de_DE.UTF-8", "36.893.488.147.419.103.232", 0x1.0p65, 26 }
> - };
> -#define ntests (sizeof (tests) / sizeof (tests[0]))
> - size_t n;
> - int result = 0;
> - for (n = 0; n < ntests; ++n)
> - {
> - double d;
> - char *endp;
Moved lower, ok.
> +#include "tst-strtod.h"
Ok.
> +/* This tests internal interfaces, which are only defined for types
> + with distinct ABIs, so diable testing for types without distinct
> + ABIs. */
spelling: s/diable/disable/ ?
> +#undef IF_FLOAT32
> +#define IF_FLOAT32(x)
> +#undef IF_FLOAT64
> +#define IF_FLOAT64(x)
> +#undef IF_FLOAT32X
> +#define IF_FLOAT32X(x)
> +#undef IF_FLOAT64X
> +#define IF_FLOAT64X(x)
> +#if !__HAVE_DISTINCT_FLOAT128
> +# undef IF_FLOAT128
> +# define IF_FLOAT128(x)
> +#endif
Ok.
> - if (setlocale (LC_ALL, tests[n].loc) == NULL)
> - {
> - printf ("cannot set locale %s\n", tests[n].loc);
> - result = 1;
> - continue;
> - }
Moved, ok
> +#define ntests (sizeof (tests) / sizeof (tests[0]))
Ok as it's only used when tests is defined.
> - d = __strtod_internal (tests[n].str, &endp, 1);
> - if (d != tests[n].exp)
> - {
> - printf ("strtod(\"%s\") returns %g and not %g\n",
> - tests[n].str, d, tests[n].exp);
> - result = 1;
> - }
> - else if (endp - tests[n].str != tests[n].nread)
> - {
> - printf ("strtod(\"%s\") read %td bytes and not %td\n",
> - tests[n].str, endp - tests[n].str, tests[n].nread);
> - result = 1;
> - }
> - }
Moved, ok
> +/* Perform a few tests in a locale with thousands separators. */
> +#define TEST_STRTOD(FSUF, FTYPE, FTOSTR, LSUF, CSUF) \
FSUF = function suffix
LSUF = literal suffix?
CSUF = copysign suffix
> +static int \
> +test_strto ## FSUF (void) \
> +{ \
> + static const struct \
> + { \
> + const char *loc; \
> + const char *str; \
> + FTYPE exp; \
> + ptrdiff_t nread; \
> + } tests[] = \
> + { \
> + { "de_DE.UTF-8", "1,5", 1.5 ## LSUF, 3 }, \
> + { "de_DE.UTF-8", "1.5", 1.0 ## LSUF, 1 }, \
> + { "de_DE.UTF-8", "1.500", 1500.0 ## LSUF, 5 }, \
> + { "de_DE.UTF-8", "36.893.488.147.419.103.232", 0x1.0p65 ## LSUF, 26 } \
> + }; \
> + size_t n; \
> + int result = 0; \
> + \
> + puts ("\nLocale tests"); \
> + \
> + for (n = 0; n < ntests; ++n) \
> + { \
> + FTYPE d; \
> + char *endp; \
> + \
> + if (setlocale (LC_ALL, tests[n].loc) == NULL) \
> + { \
> + printf ("cannot set locale %s\n", tests[n].loc); \
> + result = 1; \
> + continue; \
> + } \
> + \
> + d = __strto ## FSUF ## _internal (tests[n].str, &endp, 1); \
> + if (d != tests[n].exp) \
> + { \
> + char buf1[FSTRLENMAX], buf2[FSTRLENMAX]; \
> + FTOSTR (buf1, sizeof (buf1), "%g", d); \
> + FTOSTR (buf2, sizeof (buf2), "%g", tests[n].exp); \
Don't we need "%lg" here for long double? Ah, the function itself
defines the "l" part. Ok.
> + printf ("strto" # FSUF "(\"%s\") returns %s and not %s\n", \
> + tests[n].str, buf1, buf2); \
> + result = 1; \
> + } \
> + else if (endp - tests[n].str != tests[n].nread) \
> + { \
> + printf ("strto" # FSUF "(\"%s\") read %td bytes and not %td\n", \
> + tests[n].str, endp - tests[n].str, tests[n].nread); \
> + result = 1; \
> + } \
> + } \
Ok.
> + if (result == 0) \
> + puts ("all OK"); \
> + \
> + return result ? EXIT_FAILURE : EXIT_SUCCESS; \
> +}
Ok.
> - if (result == 0)
> - puts ("all OK");
> +GEN_TEST_STRTOD_FOREACH (TEST_STRTOD)
Invokes TEST_STRTOD three times, creating three functions, ok
> - return result ? EXIT_FAILURE : EXIT_SUCCESS;
> +static int
> +do_test (void)
> +{
> + return STRTOD_TEST_FOREACH (test_strto);
> }
Same, but alls those three functions. Ok.
> #include <support/test-driver.c>
> diff --git a/stdlib/tst-strtod3.c b/stdlib/tst-strtod3.c
> index 23abec1896..fc4efd44d1 100644
> --- a/stdlib/tst-strtod3.c
> +++ b/stdlib/tst-strtod3.c
> @@ -3,19 +3,73 @@
> #include <stdlib.h>
> #include <string.h>
>
> -static const struct
> -{
> - const char *in;
> - const char *out;
> - double expected;
> -} tests[] =
> - {
> - { "000,,,e1", ",,,e1", 0.0 },
> - { "000e1", "", 0.0 },
> - { "000,1e1", ",1e1", 0.0 }
> - };
> -#define NTESTS (sizeof (tests) / sizeof (tests[0]))
> +#include "tst-strtod.h"
> +
> +/* This tests internal interfaces, which are only defined for types
> + with distinct ABIs, so diable testing for types without distinct
Again, s/diable/disable/
> + ABIs. */
> +#undef IF_FLOAT32
> +#define IF_FLOAT32(x)
> +#undef IF_FLOAT64
> +#define IF_FLOAT64(x)
> +#undef IF_FLOAT32X
> +#define IF_FLOAT32X(x)
> +#undef IF_FLOAT64X
> +#define IF_FLOAT64X(x)
> +#if !__HAVE_DISTINCT_FLOAT128
> +# undef IF_FLOAT128
> +# define IF_FLOAT128(x)
> +#endif
Ok.
> +#define TEST_STRTOD(FSUF, FTYPE, FTOSTR, LSUF, CSUF) \
> +static const struct \
> +{ \
> + const char *in; \
> + const char *out; \
> + FTYPE expected; \
> +} tests_strto ## FSUF[] = \
> + { \
> + { "000,,,e1", ",,,e1", 0.0 ## LSUF }, \
> + { "000e1", "", 0.0 ## LSUF }, \
> + { "000,1e1", ",1e1", 0.0 ## LSUF } \
> + }; \
I'm curious how this isn't locale-dependent, but it's not new code
so... it worked before? ok ;-)
> +static int \
> +test_strto ## FSUF (void) \
> +{ \
> + int status = 0; \
> + \
> + for (int i = 0; \
> + i < sizeof (tests_strto ## FSUF) / sizeof (tests_strto ## FSUF[0]); \
> + ++i) \
> + { \
> + char *ep; \
> + FTYPE r = __strto ## FSUF ## _internal (tests_strto ## FSUF[i].in, \
> + &ep, 1); \
> + \
> + if (strcmp (ep, tests_strto ## FSUF[i].out) != 0) \
> + { \
> + printf ("%d: got rest string \"%s\", expected \"%s\"\n", \
> + i, ep, tests_strto ## FSUF[i].out); \
> + status = 1; \
> + } \
> + \
> + if (r != tests_strto ## FSUF[i].expected) \
> + { \
> + char buf1[FSTRLENMAX], buf2[FSTRLENMAX]; \
> + FTOSTR (buf1, sizeof (buf1), "%g", r); \
> + FTOSTR (buf2, sizeof (buf2), "%g", \
> + tests_strto ## FSUF[i].expected); \
> + printf ("%d: got wrong results %s, expected %s\n", \
> + i, buf1, buf2); \
> + status = 1; \
> + } \
> + } \
> + \
> + return status; \
> +}
> +
Ok.
> +GEN_TEST_STRTOD_FOREACH (TEST_STRTOD)
Ok.
> static int
> do_test (void)
> @@ -26,29 +80,7 @@ do_test (void)
> return 1;
> }
>
> - int status = 0;
> -
> - for (int i = 0; i < NTESTS; ++i)
> - {
> - char *ep;
> - double r = __strtod_internal (tests[i].in, &ep, 1);
> -
> - if (strcmp (ep, tests[i].out) != 0)
> - {
> - printf ("%d: got rest string \"%s\", expected \"%s\"\n",
> - i, ep, tests[i].out);
> - status = 1;
> - }
> -
> - if (r != tests[i].expected)
> - {
> - printf ("%d: got wrong results %g, expected %g\n",
> - i, r, tests[i].expected);
> - status = 1;
> - }
> - }
> -
> - return status;
> + return STRTOD_TEST_FOREACH (test_strto);
> }
Ok.
> diff --git a/stdlib/tst-strtod4.c b/stdlib/tst-strtod4.c
> index 6cc4e843c7..d4e569e8fc 100644
> --- a/stdlib/tst-strtod4.c
> +++ b/stdlib/tst-strtod4.c
> @@ -3,22 +3,76 @@
> #include <stdlib.h>
> #include <string.h>
>
> +#include "tst-strtod.h"
> +
> +/* This tests internal interfaces, which are only defined for types
> + with distinct ABIs, so diable testing for types without distinct
> + ABIs. */
> +#undef IF_FLOAT32
> +#define IF_FLOAT32(x)
> +#undef IF_FLOAT64
> +#define IF_FLOAT64(x)
> +#undef IF_FLOAT32X
> +#define IF_FLOAT32X(x)
> +#undef IF_FLOAT64X
> +#define IF_FLOAT64X(x)
> +#if !__HAVE_DISTINCT_FLOAT128
> +# undef IF_FLOAT128
> +# define IF_FLOAT128(x)
> +#endif
> +
Ok.
> #define NNBSP "\xe2\x80\xaf"
>
> -static const struct
> -{
> - const char *in;
> - const char *out;
> - double expected;
> -} tests[] =
> - {
> - { "000"NNBSP"000"NNBSP"000", "", 0.0 },
> - { "1"NNBSP"000"NNBSP"000,5x", "x", 1000000.5 },
> - /* Bug 30964 */
> - { "10"NNBSP NNBSP"200", NNBSP NNBSP"200", 10.0 }
> - };
> -#define NTESTS (sizeof (tests) / sizeof (tests[0]))
> +#define TEST_STRTOD(FSUF, FTYPE, FTOSTR, LSUF, CSUF) \
> +static const struct \
> +{ \
> + const char *in; \
> + const char *out; \
> + FTYPE expected; \
> +} tests_strto ## FSUF[] = \
> + { \
> + { "000"NNBSP"000"NNBSP"000", "", 0.0 ## LSUF }, \
> + { "1"NNBSP"000"NNBSP"000,5x", "x", 1000000.5 ## LSUF }, \
> + /* Bug 30964 */ \
> + { "10"NNBSP NNBSP"200", NNBSP NNBSP"200", 10.0 ## LSUF } \
> + }; \
> + \
Ok.
> +static int \
> +test_strto ## FSUF (void) \
> +{ \
> + int status = 0; \
> + \
> + for (int i = 0; \
> + i < sizeof (tests_strto ## FSUF) / sizeof (tests_strto ## FSUF[0]); \
> + ++i) \
> + { \
> + char *ep; \
> + FTYPE r = __strto ## FSUF ## _internal (tests_strto ## FSUF[i].in, \
> + &ep, 1); \
> + \
> + if (strcmp (ep, tests_strto ## FSUF[i].out) != 0) \
> + { \
> + printf ("%d: got rest string \"%s\", expected \"%s\"\n", \
> + i, ep, tests_strto ## FSUF[i].out); \
> + status = 1; \
> + } \
> + \
> + if (r != tests_strto ## FSUF[i].expected) \
> + { \
> + char buf1[FSTRLENMAX], buf2[FSTRLENMAX]; \
> + FTOSTR (buf1, sizeof (buf1), "%g", r); \
> + FTOSTR (buf2, sizeof (buf2), "%g", \
> + tests_strto ## FSUF[i].expected); \
> + printf ("%d: got wrong results %s, expected %s\n", \
> + i, buf1, buf2); \
> + status = 1; \
> + } \
> + } \
> + \
> + return status; \
> +}
Ok.
> +GEN_TEST_STRTOD_FOREACH (TEST_STRTOD)
Ok.
> static int
> do_test (void)
> @@ -29,29 +83,7 @@ do_test (void)
> return 1;
> }
>
> - int status = 0;
> -
> - for (int i = 0; i < NTESTS; ++i)
> - {
> - char *ep;
> - double r = __strtod_internal (tests[i].in, &ep, 1);
> -
> - if (strcmp (ep, tests[i].out) != 0)
> - {
> - printf ("%d: got rest string \"%s\", expected \"%s\"\n",
> - i, ep, tests[i].out);
> - status = 1;
> - }
> -
> - if (r != tests[i].expected)
> - {
> - printf ("%d: got wrong results %g, expected %g\n",
> - i, r, tests[i].expected);
> - status = 1;
> - }
> - }
> -
> - return status;
> + return STRTOD_TEST_FOREACH (test_strto);
> }
Ok.
> diff --git a/stdlib/tst-strtod5i.c b/stdlib/tst-strtod5i.c
> index ee54e3404c..aaae486884 100644
> --- a/stdlib/tst-strtod5i.c
> +++ b/stdlib/tst-strtod5i.c
> @@ -16,52 +16,112 @@
> License along with the GNU C Library; if not, see
> <https://www.gnu.org/licenses/>. */
>
> +/* Defining _LIBC_TEST ensures long double math functions are
> + declared in the headers. */
> +#define _LIBC_TEST 1
> #include <locale.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
> #include <math.h>
>
> +#include "tst-strtod.h"
> +
> +/* This tests internal interfaces, which are only defined for types
> + with distinct ABIs, so diable testing for types without distinct
> + ABIs. */
> +#undef IF_FLOAT32
> +#define IF_FLOAT32(x)
> +#undef IF_FLOAT64
> +#define IF_FLOAT64(x)
> +#undef IF_FLOAT32X
> +#define IF_FLOAT32X(x)
> +#undef IF_FLOAT64X
> +#define IF_FLOAT64X(x)
> +#if !__HAVE_DISTINCT_FLOAT128
> +# undef IF_FLOAT128
> +# define IF_FLOAT128(x)
> +#endif
> +
Ok.
> #define NNBSP "\xe2\x80\xaf"
>
> -static const struct
> -{
> - const char *in;
> - int group;
> - double expected;
> -} tests[] =
> - {
> - { "0", 0, 0.0 },
> - { "000", 0, 0.0 },
> - { "-0", 0, -0.0 },
> - { "-000", 0, -0.0 },
> - { "0,", 0, 0.0 },
> - { "-0,", 0, -0.0 },
> - { "0,0", 0, 0.0 },
> - { "-0,0", 0, -0.0 },
> - { "0e-10", 0, 0.0 },
> - { "-0e-10", 0, -0.0 },
> - { "0,e-10", 0, 0.0 },
> - { "-0,e-10", 0, -0.0 },
> - { "0,0e-10", 0, 0.0 },
> - { "-0,0e-10", 0, -0.0 },
> - { "0e-1000000", 0, 0.0 },
> - { "-0e-1000000", 0, -0.0 },
> - { "0,0e-1000000", 0, 0.0 },
> - { "-0,0e-1000000", 0, -0.0 },
> - { "0", 1, 0.0 },
> - { "000", 1, 0.0 },
> - { "-0", 1, -0.0 },
> - { "-000", 1, -0.0 },
> - { "0e-10", 1, 0.0 },
> - { "-0e-10", 1, -0.0 },
> - { "0e-1000000", 1, 0.0 },
> - { "-0e-1000000", 1, -0.0 },
> - { "000"NNBSP"000"NNBSP"000", 1, 0.0 },
> - { "-000"NNBSP"000"NNBSP"000", 1, -0.0 }
> - };
> -#define NTESTS (sizeof (tests) / sizeof (tests[0]))
> +#define TEST_STRTOD(FSUF, FTYPE, FTOSTR, LSUF, CSUF) \
> +static const struct \
> +{ \
> + const char *in; \
> + int group; \
> + FTYPE expected; \
> +} tests_strto ## FSUF[] = \
> + { \
> + { "0", 0, 0.0 ## LSUF }, \
> + { "000", 0, 0.0 ## LSUF }, \
> + { "-0", 0, -0.0 ## LSUF }, \
> + { "-000", 0, -0.0 ## LSUF }, \
> + { "0,", 0, 0.0 ## LSUF }, \
> + { "-0,", 0, -0.0 ## LSUF }, \
> + { "0,0", 0, 0.0 ## LSUF }, \
> + { "-0,0", 0, -0.0 ## LSUF }, \
> + { "0e-10", 0, 0.0 ## LSUF }, \
> + { "-0e-10", 0, -0.0 ## LSUF }, \
> + { "0,e-10", 0, 0.0 ## LSUF }, \
> + { "-0,e-10", 0, -0.0 ## LSUF }, \
> + { "0,0e-10", 0, 0.0 ## LSUF }, \
> + { "-0,0e-10", 0, -0.0 ## LSUF }, \
> + { "0e-1000000", 0, 0.0 ## LSUF }, \
> + { "-0e-1000000", 0, -0.0 ## LSUF }, \
> + { "0,0e-1000000", 0, 0.0 ## LSUF }, \
> + { "-0,0e-1000000", 0, -0.0 ## LSUF }, \
> + { "0", 1, 0.0 ## LSUF }, \
> + { "000", 1, 0.0 ## LSUF }, \
> + { "-0", 1, -0.0 ## LSUF }, \
> + { "-000", 1, -0.0 ## LSUF }, \
> + { "0e-10", 1, 0.0 ## LSUF }, \
> + { "-0e-10", 1, -0.0 ## LSUF }, \
> + { "0e-1000000", 1, 0.0 ## LSUF }, \
> + { "-0e-1000000", 1, -0.0 ## LSUF }, \
> + { "000"NNBSP"000"NNBSP"000", 1, 0.0 ## LSUF }, \
> + { "-000"NNBSP"000"NNBSP"000", 1, -0.0 ## LSUF } \
> + }; \
> + \
Ok.
> +static int \
> +test_strto ## FSUF (void) \
> +{ \
> + int status = 0; \
> + \
> + for (int i = 0; \
> + i < sizeof (tests_strto ## FSUF) / sizeof (tests_strto ## FSUF[0]); \
> + ++i) \
> + { \
> + char *ep; \
> + FTYPE r = __strto ## FSUF ## _internal (tests_strto ## FSUF[i].in, \
> + &ep, \
> + tests_strto ## FSUF[i].group); \
> + \
> + if (*ep != '\0') \
> + { \
> + printf ("%d: got rest string \"%s\", expected \"\"\n", i, ep); \
> + status = 1; \
> + } \
> + \
> + if (r != tests_strto ## FSUF[i].expected \
> + || (copysign ## CSUF (10.0 ## LSUF, r) \
> + != copysign ## CSUF (10.0 ## LSUF, \
> + tests_strto ## FSUF[i].expected))) \
> + { \
> + char buf1[FSTRLENMAX], buf2[FSTRLENMAX]; \
> + FTOSTR (buf1, sizeof (buf1), "%g", r); \
> + FTOSTR (buf2, sizeof (buf2), "%g", \
> + tests_strto ## FSUF[i].expected); \
> + printf ("%d: got wrong results %s, expected %s\n", \
> + i, buf1, buf2); \
> + status = 1; \
> + } \
> + } \
> + \
> + return status; \
> +}
>
> +GEN_TEST_STRTOD_FOREACH (TEST_STRTOD)
Ok.
> static int
> do_test (void)
> @@ -72,29 +132,7 @@ do_test (void)
> return 1;
> }
>
> - int status = 0;
> -
> - for (int i = 0; i < NTESTS; ++i)
> - {
> - char *ep;
> - double r = __strtod_internal (tests[i].in, &ep, tests[i].group);
> -
> - if (*ep != '\0')
> - {
> - printf ("%d: got rest string \"%s\", expected \"\"\n", i, ep);
> - status = 1;
> - }
> -
> - if (r != tests[i].expected
> - || copysign (10.0, r) != copysign (10.0, tests[i].expected))
> - {
> - printf ("%d: got wrong results %g, expected %g\n",
> - i, r, tests[i].expected);
> - status = 1;
> - }
> - }
> -
> - return status;
> + return STRTOD_TEST_FOREACH (test_strto);
> }
>
> #include <support/test-driver.c>
Ok.
@@ -25,60 +25,91 @@
#include <string.h>
#include <math.h>
-/* Perform a few tests in a locale with thousands separators. */
-static int
-do_test (void)
-{
- static const struct
- {
- const char *loc;
- const char *str;
- double exp;
- ptrdiff_t nread;
- } tests[] =
- {
- { "de_DE.UTF-8", "1,5", 1.5, 3 },
- { "de_DE.UTF-8", "1.5", 1.0, 1 },
- { "de_DE.UTF-8", "1.500", 1500.0, 5 },
- { "de_DE.UTF-8", "36.893.488.147.419.103.232", 0x1.0p65, 26 }
- };
-#define ntests (sizeof (tests) / sizeof (tests[0]))
- size_t n;
- int result = 0;
-
- puts ("\nLocale tests");
+#include "tst-strtod.h"
- for (n = 0; n < ntests; ++n)
- {
- double d;
- char *endp;
+/* This tests internal interfaces, which are only defined for types
+ with distinct ABIs, so diable testing for types without distinct
+ ABIs. */
+#undef IF_FLOAT32
+#define IF_FLOAT32(x)
+#undef IF_FLOAT64
+#define IF_FLOAT64(x)
+#undef IF_FLOAT32X
+#define IF_FLOAT32X(x)
+#undef IF_FLOAT64X
+#define IF_FLOAT64X(x)
+#if !__HAVE_DISTINCT_FLOAT128
+# undef IF_FLOAT128
+# define IF_FLOAT128(x)
+#endif
- if (setlocale (LC_ALL, tests[n].loc) == NULL)
- {
- printf ("cannot set locale %s\n", tests[n].loc);
- result = 1;
- continue;
- }
+#define ntests (sizeof (tests) / sizeof (tests[0]))
- d = __strtod_internal (tests[n].str, &endp, 1);
- if (d != tests[n].exp)
- {
- printf ("strtod(\"%s\") returns %g and not %g\n",
- tests[n].str, d, tests[n].exp);
- result = 1;
- }
- else if (endp - tests[n].str != tests[n].nread)
- {
- printf ("strtod(\"%s\") read %td bytes and not %td\n",
- tests[n].str, endp - tests[n].str, tests[n].nread);
- result = 1;
- }
- }
+/* Perform a few tests in a locale with thousands separators. */
+#define TEST_STRTOD(FSUF, FTYPE, FTOSTR, LSUF, CSUF) \
+static int \
+test_strto ## FSUF (void) \
+{ \
+ static const struct \
+ { \
+ const char *loc; \
+ const char *str; \
+ FTYPE exp; \
+ ptrdiff_t nread; \
+ } tests[] = \
+ { \
+ { "de_DE.UTF-8", "1,5", 1.5 ## LSUF, 3 }, \
+ { "de_DE.UTF-8", "1.5", 1.0 ## LSUF, 1 }, \
+ { "de_DE.UTF-8", "1.500", 1500.0 ## LSUF, 5 }, \
+ { "de_DE.UTF-8", "36.893.488.147.419.103.232", 0x1.0p65 ## LSUF, 26 } \
+ }; \
+ size_t n; \
+ int result = 0; \
+ \
+ puts ("\nLocale tests"); \
+ \
+ for (n = 0; n < ntests; ++n) \
+ { \
+ FTYPE d; \
+ char *endp; \
+ \
+ if (setlocale (LC_ALL, tests[n].loc) == NULL) \
+ { \
+ printf ("cannot set locale %s\n", tests[n].loc); \
+ result = 1; \
+ continue; \
+ } \
+ \
+ d = __strto ## FSUF ## _internal (tests[n].str, &endp, 1); \
+ if (d != tests[n].exp) \
+ { \
+ char buf1[FSTRLENMAX], buf2[FSTRLENMAX]; \
+ FTOSTR (buf1, sizeof (buf1), "%g", d); \
+ FTOSTR (buf2, sizeof (buf2), "%g", tests[n].exp); \
+ printf ("strto" # FSUF "(\"%s\") returns %s and not %s\n", \
+ tests[n].str, buf1, buf2); \
+ result = 1; \
+ } \
+ else if (endp - tests[n].str != tests[n].nread) \
+ { \
+ printf ("strto" # FSUF "(\"%s\") read %td bytes and not %td\n", \
+ tests[n].str, endp - tests[n].str, tests[n].nread); \
+ result = 1; \
+ } \
+ } \
+ \
+ if (result == 0) \
+ puts ("all OK"); \
+ \
+ return result ? EXIT_FAILURE : EXIT_SUCCESS; \
+}
- if (result == 0)
- puts ("all OK");
+GEN_TEST_STRTOD_FOREACH (TEST_STRTOD)
- return result ? EXIT_FAILURE : EXIT_SUCCESS;
+static int
+do_test (void)
+{
+ return STRTOD_TEST_FOREACH (test_strto);
}
#include <support/test-driver.c>
@@ -3,19 +3,73 @@
#include <stdlib.h>
#include <string.h>
-static const struct
-{
- const char *in;
- const char *out;
- double expected;
-} tests[] =
- {
- { "000,,,e1", ",,,e1", 0.0 },
- { "000e1", "", 0.0 },
- { "000,1e1", ",1e1", 0.0 }
- };
-#define NTESTS (sizeof (tests) / sizeof (tests[0]))
+#include "tst-strtod.h"
+
+/* This tests internal interfaces, which are only defined for types
+ with distinct ABIs, so diable testing for types without distinct
+ ABIs. */
+#undef IF_FLOAT32
+#define IF_FLOAT32(x)
+#undef IF_FLOAT64
+#define IF_FLOAT64(x)
+#undef IF_FLOAT32X
+#define IF_FLOAT32X(x)
+#undef IF_FLOAT64X
+#define IF_FLOAT64X(x)
+#if !__HAVE_DISTINCT_FLOAT128
+# undef IF_FLOAT128
+# define IF_FLOAT128(x)
+#endif
+#define TEST_STRTOD(FSUF, FTYPE, FTOSTR, LSUF, CSUF) \
+static const struct \
+{ \
+ const char *in; \
+ const char *out; \
+ FTYPE expected; \
+} tests_strto ## FSUF[] = \
+ { \
+ { "000,,,e1", ",,,e1", 0.0 ## LSUF }, \
+ { "000e1", "", 0.0 ## LSUF }, \
+ { "000,1e1", ",1e1", 0.0 ## LSUF } \
+ }; \
+ \
+static int \
+test_strto ## FSUF (void) \
+{ \
+ int status = 0; \
+ \
+ for (int i = 0; \
+ i < sizeof (tests_strto ## FSUF) / sizeof (tests_strto ## FSUF[0]); \
+ ++i) \
+ { \
+ char *ep; \
+ FTYPE r = __strto ## FSUF ## _internal (tests_strto ## FSUF[i].in, \
+ &ep, 1); \
+ \
+ if (strcmp (ep, tests_strto ## FSUF[i].out) != 0) \
+ { \
+ printf ("%d: got rest string \"%s\", expected \"%s\"\n", \
+ i, ep, tests_strto ## FSUF[i].out); \
+ status = 1; \
+ } \
+ \
+ if (r != tests_strto ## FSUF[i].expected) \
+ { \
+ char buf1[FSTRLENMAX], buf2[FSTRLENMAX]; \
+ FTOSTR (buf1, sizeof (buf1), "%g", r); \
+ FTOSTR (buf2, sizeof (buf2), "%g", \
+ tests_strto ## FSUF[i].expected); \
+ printf ("%d: got wrong results %s, expected %s\n", \
+ i, buf1, buf2); \
+ status = 1; \
+ } \
+ } \
+ \
+ return status; \
+}
+
+GEN_TEST_STRTOD_FOREACH (TEST_STRTOD)
static int
do_test (void)
@@ -26,29 +80,7 @@ do_test (void)
return 1;
}
- int status = 0;
-
- for (int i = 0; i < NTESTS; ++i)
- {
- char *ep;
- double r = __strtod_internal (tests[i].in, &ep, 1);
-
- if (strcmp (ep, tests[i].out) != 0)
- {
- printf ("%d: got rest string \"%s\", expected \"%s\"\n",
- i, ep, tests[i].out);
- status = 1;
- }
-
- if (r != tests[i].expected)
- {
- printf ("%d: got wrong results %g, expected %g\n",
- i, r, tests[i].expected);
- status = 1;
- }
- }
-
- return status;
+ return STRTOD_TEST_FOREACH (test_strto);
}
#define TEST_FUNCTION do_test ()
@@ -3,22 +3,76 @@
#include <stdlib.h>
#include <string.h>
+#include "tst-strtod.h"
+
+/* This tests internal interfaces, which are only defined for types
+ with distinct ABIs, so diable testing for types without distinct
+ ABIs. */
+#undef IF_FLOAT32
+#define IF_FLOAT32(x)
+#undef IF_FLOAT64
+#define IF_FLOAT64(x)
+#undef IF_FLOAT32X
+#define IF_FLOAT32X(x)
+#undef IF_FLOAT64X
+#define IF_FLOAT64X(x)
+#if !__HAVE_DISTINCT_FLOAT128
+# undef IF_FLOAT128
+# define IF_FLOAT128(x)
+#endif
+
#define NNBSP "\xe2\x80\xaf"
-static const struct
-{
- const char *in;
- const char *out;
- double expected;
-} tests[] =
- {
- { "000"NNBSP"000"NNBSP"000", "", 0.0 },
- { "1"NNBSP"000"NNBSP"000,5x", "x", 1000000.5 },
- /* Bug 30964 */
- { "10"NNBSP NNBSP"200", NNBSP NNBSP"200", 10.0 }
- };
-#define NTESTS (sizeof (tests) / sizeof (tests[0]))
+#define TEST_STRTOD(FSUF, FTYPE, FTOSTR, LSUF, CSUF) \
+static const struct \
+{ \
+ const char *in; \
+ const char *out; \
+ FTYPE expected; \
+} tests_strto ## FSUF[] = \
+ { \
+ { "000"NNBSP"000"NNBSP"000", "", 0.0 ## LSUF }, \
+ { "1"NNBSP"000"NNBSP"000,5x", "x", 1000000.5 ## LSUF }, \
+ /* Bug 30964 */ \
+ { "10"NNBSP NNBSP"200", NNBSP NNBSP"200", 10.0 ## LSUF } \
+ }; \
+ \
+static int \
+test_strto ## FSUF (void) \
+{ \
+ int status = 0; \
+ \
+ for (int i = 0; \
+ i < sizeof (tests_strto ## FSUF) / sizeof (tests_strto ## FSUF[0]); \
+ ++i) \
+ { \
+ char *ep; \
+ FTYPE r = __strto ## FSUF ## _internal (tests_strto ## FSUF[i].in, \
+ &ep, 1); \
+ \
+ if (strcmp (ep, tests_strto ## FSUF[i].out) != 0) \
+ { \
+ printf ("%d: got rest string \"%s\", expected \"%s\"\n", \
+ i, ep, tests_strto ## FSUF[i].out); \
+ status = 1; \
+ } \
+ \
+ if (r != tests_strto ## FSUF[i].expected) \
+ { \
+ char buf1[FSTRLENMAX], buf2[FSTRLENMAX]; \
+ FTOSTR (buf1, sizeof (buf1), "%g", r); \
+ FTOSTR (buf2, sizeof (buf2), "%g", \
+ tests_strto ## FSUF[i].expected); \
+ printf ("%d: got wrong results %s, expected %s\n", \
+ i, buf1, buf2); \
+ status = 1; \
+ } \
+ } \
+ \
+ return status; \
+}
+GEN_TEST_STRTOD_FOREACH (TEST_STRTOD)
static int
do_test (void)
@@ -29,29 +83,7 @@ do_test (void)
return 1;
}
- int status = 0;
-
- for (int i = 0; i < NTESTS; ++i)
- {
- char *ep;
- double r = __strtod_internal (tests[i].in, &ep, 1);
-
- if (strcmp (ep, tests[i].out) != 0)
- {
- printf ("%d: got rest string \"%s\", expected \"%s\"\n",
- i, ep, tests[i].out);
- status = 1;
- }
-
- if (r != tests[i].expected)
- {
- printf ("%d: got wrong results %g, expected %g\n",
- i, r, tests[i].expected);
- status = 1;
- }
- }
-
- return status;
+ return STRTOD_TEST_FOREACH (test_strto);
}
#define TEST_FUNCTION do_test ()
@@ -16,52 +16,112 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
+/* Defining _LIBC_TEST ensures long double math functions are
+ declared in the headers. */
+#define _LIBC_TEST 1
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
+#include "tst-strtod.h"
+
+/* This tests internal interfaces, which are only defined for types
+ with distinct ABIs, so diable testing for types without distinct
+ ABIs. */
+#undef IF_FLOAT32
+#define IF_FLOAT32(x)
+#undef IF_FLOAT64
+#define IF_FLOAT64(x)
+#undef IF_FLOAT32X
+#define IF_FLOAT32X(x)
+#undef IF_FLOAT64X
+#define IF_FLOAT64X(x)
+#if !__HAVE_DISTINCT_FLOAT128
+# undef IF_FLOAT128
+# define IF_FLOAT128(x)
+#endif
+
#define NNBSP "\xe2\x80\xaf"
-static const struct
-{
- const char *in;
- int group;
- double expected;
-} tests[] =
- {
- { "0", 0, 0.0 },
- { "000", 0, 0.0 },
- { "-0", 0, -0.0 },
- { "-000", 0, -0.0 },
- { "0,", 0, 0.0 },
- { "-0,", 0, -0.0 },
- { "0,0", 0, 0.0 },
- { "-0,0", 0, -0.0 },
- { "0e-10", 0, 0.0 },
- { "-0e-10", 0, -0.0 },
- { "0,e-10", 0, 0.0 },
- { "-0,e-10", 0, -0.0 },
- { "0,0e-10", 0, 0.0 },
- { "-0,0e-10", 0, -0.0 },
- { "0e-1000000", 0, 0.0 },
- { "-0e-1000000", 0, -0.0 },
- { "0,0e-1000000", 0, 0.0 },
- { "-0,0e-1000000", 0, -0.0 },
- { "0", 1, 0.0 },
- { "000", 1, 0.0 },
- { "-0", 1, -0.0 },
- { "-000", 1, -0.0 },
- { "0e-10", 1, 0.0 },
- { "-0e-10", 1, -0.0 },
- { "0e-1000000", 1, 0.0 },
- { "-0e-1000000", 1, -0.0 },
- { "000"NNBSP"000"NNBSP"000", 1, 0.0 },
- { "-000"NNBSP"000"NNBSP"000", 1, -0.0 }
- };
-#define NTESTS (sizeof (tests) / sizeof (tests[0]))
+#define TEST_STRTOD(FSUF, FTYPE, FTOSTR, LSUF, CSUF) \
+static const struct \
+{ \
+ const char *in; \
+ int group; \
+ FTYPE expected; \
+} tests_strto ## FSUF[] = \
+ { \
+ { "0", 0, 0.0 ## LSUF }, \
+ { "000", 0, 0.0 ## LSUF }, \
+ { "-0", 0, -0.0 ## LSUF }, \
+ { "-000", 0, -0.0 ## LSUF }, \
+ { "0,", 0, 0.0 ## LSUF }, \
+ { "-0,", 0, -0.0 ## LSUF }, \
+ { "0,0", 0, 0.0 ## LSUF }, \
+ { "-0,0", 0, -0.0 ## LSUF }, \
+ { "0e-10", 0, 0.0 ## LSUF }, \
+ { "-0e-10", 0, -0.0 ## LSUF }, \
+ { "0,e-10", 0, 0.0 ## LSUF }, \
+ { "-0,e-10", 0, -0.0 ## LSUF }, \
+ { "0,0e-10", 0, 0.0 ## LSUF }, \
+ { "-0,0e-10", 0, -0.0 ## LSUF }, \
+ { "0e-1000000", 0, 0.0 ## LSUF }, \
+ { "-0e-1000000", 0, -0.0 ## LSUF }, \
+ { "0,0e-1000000", 0, 0.0 ## LSUF }, \
+ { "-0,0e-1000000", 0, -0.0 ## LSUF }, \
+ { "0", 1, 0.0 ## LSUF }, \
+ { "000", 1, 0.0 ## LSUF }, \
+ { "-0", 1, -0.0 ## LSUF }, \
+ { "-000", 1, -0.0 ## LSUF }, \
+ { "0e-10", 1, 0.0 ## LSUF }, \
+ { "-0e-10", 1, -0.0 ## LSUF }, \
+ { "0e-1000000", 1, 0.0 ## LSUF }, \
+ { "-0e-1000000", 1, -0.0 ## LSUF }, \
+ { "000"NNBSP"000"NNBSP"000", 1, 0.0 ## LSUF }, \
+ { "-000"NNBSP"000"NNBSP"000", 1, -0.0 ## LSUF } \
+ }; \
+ \
+static int \
+test_strto ## FSUF (void) \
+{ \
+ int status = 0; \
+ \
+ for (int i = 0; \
+ i < sizeof (tests_strto ## FSUF) / sizeof (tests_strto ## FSUF[0]); \
+ ++i) \
+ { \
+ char *ep; \
+ FTYPE r = __strto ## FSUF ## _internal (tests_strto ## FSUF[i].in, \
+ &ep, \
+ tests_strto ## FSUF[i].group); \
+ \
+ if (*ep != '\0') \
+ { \
+ printf ("%d: got rest string \"%s\", expected \"\"\n", i, ep); \
+ status = 1; \
+ } \
+ \
+ if (r != tests_strto ## FSUF[i].expected \
+ || (copysign ## CSUF (10.0 ## LSUF, r) \
+ != copysign ## CSUF (10.0 ## LSUF, \
+ tests_strto ## FSUF[i].expected))) \
+ { \
+ char buf1[FSTRLENMAX], buf2[FSTRLENMAX]; \
+ FTOSTR (buf1, sizeof (buf1), "%g", r); \
+ FTOSTR (buf2, sizeof (buf2), "%g", \
+ tests_strto ## FSUF[i].expected); \
+ printf ("%d: got wrong results %s, expected %s\n", \
+ i, buf1, buf2); \
+ status = 1; \
+ } \
+ } \
+ \
+ return status; \
+}
+GEN_TEST_STRTOD_FOREACH (TEST_STRTOD)
static int
do_test (void)
@@ -72,29 +132,7 @@ do_test (void)
return 1;
}
- int status = 0;
-
- for (int i = 0; i < NTESTS; ++i)
- {
- char *ep;
- double r = __strtod_internal (tests[i].in, &ep, tests[i].group);
-
- if (*ep != '\0')
- {
- printf ("%d: got rest string \"%s\", expected \"\"\n", i, ep);
- status = 1;
- }
-
- if (r != tests[i].expected
- || copysign (10.0, r) != copysign (10.0, tests[i].expected))
- {
- printf ("%d: got wrong results %g, expected %g\n",
- i, r, tests[i].expected);
- status = 1;
- }
- }
-
- return status;
+ return STRTOD_TEST_FOREACH (test_strto);
}
#include <support/test-driver.c>