diff --git a/ChangeLog b/ChangeLog index dd48055546..6b8763f95a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2016-10-25 Rajalakshmi Srinivasaraghavan + * stdlib/Makefile (tests): Add tst-strfrom and tst-strfrom-locale. + * stdlib/tst-strfrom.h: New file. + * stdlib/tst-strfrom.c: New file. + * stdlib/tst-strfrom-locale.c: New file. + * stdlib/bug-strtod.c: Refactor based on GEN_TEST_STRTOD_FOREACH. * stdlib/bug-strtod2.c: Likewise. * stdlib/tst-strtod-round-skeleton.c: Likewise. diff --git a/stdlib/Makefile b/stdlib/Makefile index 3cacb8b3f6..3cce9d98d4 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -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 diff --git a/stdlib/tst-strfrom-locale.c b/stdlib/tst-strfrom-locale.c new file mode 100644 index 0000000000..08d374f7fd --- /dev/null +++ b/stdlib/tst-strfrom-locale.c @@ -0,0 +1,91 @@ +/* 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 + . */ + +#include "tst-strfrom.h" + +static const struct test tests[] = { + TEST ("12,345000", "%f", 50, 9, 12.345), + TEST ("9,999", "%.3f", 50, 5, 9.999), + TEST ("0,125000", "%f", 50, 8, .125), + TEST ("0,000000", "%f", 50, 8, .0), + TEST ("0", "%g", 50, 1, .0), + TEST ("9,900000", "%f", 50, 8, 9.9), + TEST ("9,1", "%.5f", 4, 7, 9.123456), + TEST ("9,91235", "%g", 50, 7, 9.91234567812345678), + TEST ("79,8765", "%G", 50, 7, 79.8765432111), + TEST ("79,9", "%.3g", 50, 4, 79.8765432111), + TEST ("1,000000e+38", "%e", 50, 12, 1e+38), + TEST ("1,000000e+38", "%e", 50, 12, 1e38), + TEST ("-1,000000e-37", "%e", 50, 13, -1e-37), + TEST ("1,000000e-37", "%e", 50, 12, 0.00000001e-29), + TEST ("1,000000e-37", "%e", 50, 12, 1.000000e-37), + TEST ("5,900000e-16", "%e", 50, 12, 5.9e-16), + TEST ("1,234500e+20", "%e", 50, 12, 12.345e19), + TEST ("1,000000e+05", "%e", 50, 12, 1e5), + TEST ("-NAN", "%G", 50, 4, -NAN_), + TEST ("-inf", "%g", 50, 4, -INF), + TEST ("inf", "%g", 50, 3, INF) +}; +/* Tests with buffer size small. */ +static const struct test stest[] = { + TEST ("1234", "%g", 5, 7, 12345.345), + TEST ("0,12", "%f", 5, 8, .125), + TEST ("9,99", "%.3f", 5, 5, 9.999), + TEST ("100", "%g", 5, 3, 1e2) +}; +/* Hexadecimal tests. */ +static const struct htests htest[] = { + HTEST ("%a", { "0x1,ffp+6", "0x3,fep+5", "0x7,fcp+4", "0xf,f8p+3" }, + 0x1.ffp+6), + HTEST ("%a", { "0x1,88p+4", "0x3,1p+3", "0x6,2p+2", "0xc,4p+1" }, + 0x1.88p+4), + HTEST ("%A", { "-0X1,88P+5", "-0X3,1P+4", "-0X6,2P+3", "-0XC,4P+2" }, + -0x1.88p+5), + HTEST ("%a", { "0x1,44p+10", "0x2,88p+9", "0x5,1p+8", "0xa,2p+7" }, + 0x1.44p+10), + HTEST ("%a", { "0x1p-10", "0x2p-11", "0x4p-12", "0x8p-13" }, + 0x0.0040p+0), + HTEST ("%a", { "0x1,4p+3", "0x2,8p+2", "0x5p+1", "0xap+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" diff --git a/stdlib/tst-strfrom.c b/stdlib/tst-strfrom.c new file mode 100644 index 0000000000..3c990be60b --- /dev/null +++ b/stdlib/tst-strfrom.c @@ -0,0 +1,91 @@ +/* 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 + . */ + +#include "tst-strfrom.h" + +static const struct test tests[] = { + TEST ("12.345000", "%f", 50, 9, 12.345), + TEST ("9.999", "%.3f", 50, 5, 9.999), + TEST ("0.125000", "%f", 50, 8, .125), + TEST ("0.000000", "%f", 50, 8, .0), + TEST ("0", "%g", 50, 1, .0), + TEST ("9.900000", "%f", 50, 8, 9.9), + TEST ("9.1", "%.5f", 4, 7, 9.123456), + TEST ("9.91235", "%g", 50, 7, 9.91234567812345678), + TEST ("79.8765", "%G", 50, 7, 79.8765432111), + TEST ("79.9", "%.3g", 50, 4, 79.8765432111), + TEST ("1.000000e+38", "%e", 50, 12, 1e+38), + TEST ("1.000000e+38", "%e", 50, 12, 1e38), + TEST ("-1.000000e-37", "%e", 50, 13, -1e-37), + TEST ("1.000000e-37", "%e", 50, 12, 0.00000001e-29), + TEST ("1.000000e-37", "%e", 50, 12, 1.000000e-37), + TEST ("5.900000e-16", "%e", 50, 12, 5.9e-16), + TEST ("1.234500e+20", "%e", 50, 12, 12.345e19), + TEST ("1.000000e+05", "%e", 50, 12, 1e5), + TEST ("-NAN", "%G", 50, 4, -NAN_), + TEST ("-inf", "%g", 50, 4, -INF), + TEST ("inf", "%g", 50, 3, INF) +}; +/* Tests with buffer size small. */ +static const struct test stest[] = { + TEST ("1234", "%g", 5, 7, 12345.345), + TEST ("0.12", "%f", 5, 8, .125), + TEST ("9.99", "%.3f", 5, 5, 9.999), + TEST ("100", "%g", 5, 3, 1e2) +}; +/* Hexadecimal tests. */ +static const struct htests htest[] = { + HTEST ("%a", { "0x1.ffp+6", "0x3.fep+5", "0x7.fcp+4", "0xf.f8p+3" }, + 0x1.ffp+6), + HTEST ("%a", { "0x1.88p+4", "0x3.1p+3", "0x6.2p+2", "0xc.4p+1" }, + 0x1.88p+4), + HTEST ("%A", { "-0X1.88P+5", "-0X3.1P+4", "-0X6.2P+3", "-0XC.4P+2" }, + -0x1.88p+5), + HTEST ("%a", { "0x1.44p+10", "0x2.88p+9", "0x5.1p+8", "0xa.2p+7" }, + 0x1.44p+10), + HTEST ("%a", { "0x1p-10", "0x2p-11", "0x4p-12", "0x8p-13" }, + 0x0.0040p+0), + HTEST ("%a", { "0x1.4p+3", "0x2.8p+2", "0x5p+1", "0xap+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" diff --git a/stdlib/tst-strfrom.h b/stdlib/tst-strfrom.h new file mode 100644 index 0000000000..31a6492936 --- /dev/null +++ b/stdlib/tst-strfrom.h @@ -0,0 +1,120 @@ +/* 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 + . */ + +#include +#include +#include +#include +#include +#include + +#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) + +#define ENTRY(FSUF, FTYPE, FTOSTR, LSUF, CSUF, ...) \ + CONCAT (__VA_ARGS__, CSUF), +/* 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, val) \ + { \ + s, fmt, size, rc, { GEN_TEST_STRTOD_FOREACH (ENTRY, val) } \ + } +/* Hexadecimal tests. */ +struct htests +{ + const char *fmt; + const char *exp[4]; + struct test_input t; +}; +#define HTEST(fmt, exp1, exp2, exp3, exp4, val) \ + { \ + fmt, exp1, exp2, exp3, exp4, { GEN_TEST_STRTOD_FOREACH (ENTRY, val) } \ + } + +#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; \ +}