libio: Improve fortify with clang
[glibc.git] / misc / tst-efgcvt-template.c
blob509dca9f1ab67616b1e1a094b5b2d260c15101ee
1 /* Copyright (C) 1998-2024 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <https://www.gnu.org/licenses/>. */
18 /* This template provides testing for the *cvt family of functions,
19 which deal with double or long double types. In order to use the
20 template, the following macros must be defined before inclusion of
21 this template:
23 FLOAT: The floating-point type, i.e. double or long double.
25 ECVT: Appropriate *ecvt function for FLOAT, i.e. ecvt or qecvt.
26 FCVT: Likewise for *fcvt, i.e. fcvt or qfcvt.
27 ECVT_R: Likewise for *ecvt_r, i.e. ecvt_r or qecvt_r.
28 FCVT_R: Likewise for *fcvt_r, i.e. fcvt_r or qfcvt_r.
30 PRINTF_CONVERSION: The appropriate printf conversion specifier with
31 length modifier for FLOAT, i.e. "%f" or "%Lf".
33 EXTRA_ECVT_TESTS: Additional tests for the ecvt or qecvt function
34 that are only relevant to a particular floating-point type and
35 cannot be represented generically. */
37 #ifndef _GNU_SOURCE
38 # define _GNU_SOURCE 1
39 #endif
41 #include <math.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
46 #include <support/check.h>
48 #define NAME(x) NAMEX(x)
49 #define NAMEX(x) #x
51 typedef struct
53 FLOAT value;
54 int ndigit;
55 int decpt;
56 char result[30];
57 } testcase;
59 typedef char * ((*efcvt_func) (FLOAT, int, int *, int *));
61 typedef int ((*efcvt_r_func) (FLOAT, int, int *, int *, char *, size_t));
64 static testcase ecvt_tests[] =
66 { 0.0, 0, 1, "" },
67 { 10.0, 0, 2, "" },
68 { 10.0, 1, 2, "1" },
69 { 10.0, 5, 2, "10000" },
70 { -12.0, 5, 2, "12000" },
71 { 0.2, 4, 0, "2000" },
72 { 0.02, 4, -1, "2000" },
73 { 5.5, 1, 1, "6" },
74 { 1.0, -1, 1, "" },
75 { 0.01, 2, -1, "10" },
76 { 100.0, -2, 3, "" },
77 { 100.0, -5, 3, "" },
78 { 100.0, -4, 3, "" },
79 { 100.01, -4, 3, "" },
80 { 123.01, -4, 3, "" },
81 { 126.71, -4, 3, "" },
82 { 0.0, 4, 1, "0000" },
83 EXTRA_ECVT_TESTS
84 /* -1.0 is end marker. */
85 { -1.0, 0, 0, "" }
88 static testcase fcvt_tests[] =
90 { 0.0, 0, 1, "0" },
91 { 10.0, 0, 2, "10" },
92 { 10.0, 1, 2, "100" },
93 { 10.0, 4, 2, "100000" },
94 { -12.0, 5, 2, "1200000" },
95 { 0.2, 4, 0, "2000" },
96 { 0.02, 4, -1, "200" },
97 { 5.5, 1, 1, "55" },
98 { 5.5, 0, 1, "6" },
99 { 0.01, 2, -1, "1" },
100 { 100.0, -2, 3, "100" },
101 { 100.0, -5, 3, "100" },
102 { 100.0, -4, 3, "100" },
103 { 100.01, -4, 3, "100" },
104 { 123.01, -4, 3, "100" },
105 { 126.71, -4, 3, "100" },
106 { 322.5, 16, 3, "3225000000000000000" },
107 /* -1.0 is end marker. */
108 { -1.0, 0, 0, "" }
111 static void
112 output_error (const char *name, FLOAT value, int ndigit,
113 const char *exp_p, int exp_decpt, int exp_sign,
114 char *res_p, int res_decpt, int res_sign)
116 printf ("%s returned wrong result for value: " PRINTF_CONVERSION
117 ", ndigits: %d\n",
118 name, value, ndigit);
119 printf ("Result was p: \"%s\", decpt: %d, sign: %d\n",
120 res_p, res_decpt, res_sign);
121 printf ("Should be p: \"%s\", decpt: %d, sign: %d\n",
122 exp_p, exp_decpt, exp_sign);
123 support_record_failure ();
127 static void
128 output_r_error (const char *name, FLOAT value, int ndigit,
129 const char *exp_p, int exp_decpt, int exp_sign, int exp_return,
130 char *res_p, int res_decpt, int res_sign, int res_return)
132 printf ("%s returned wrong result for value: " PRINTF_CONVERSION
133 ", ndigits: %d\n",
134 name, value, ndigit);
135 printf ("Result was buf: \"%s\", decpt: %d, sign: %d return value: %d\n",
136 res_p, res_decpt, res_sign, res_return);
137 printf ("Should be buf: \"%s\", decpt: %d, sign: %d\n",
138 exp_p, exp_decpt, exp_sign);
139 support_record_failure ();
142 static void
143 test (testcase tests[], efcvt_func efcvt, const char *name)
145 int no = 0;
146 int decpt, sign;
147 char *p;
149 while (tests[no].value != -1.0)
151 p = efcvt (tests[no].value, tests[no].ndigit, &decpt, &sign);
152 if (decpt != tests[no].decpt
153 || sign != (tests[no].value < 0)
154 || strcmp (p, tests[no].result) != 0)
155 output_error (name, tests[no].value, tests[no].ndigit,
156 tests[no].result, tests[no].decpt,
157 (tests[no].value < 0),
158 p, decpt, sign);
159 ++no;
163 static void
164 test_r (testcase tests[], efcvt_r_func efcvt_r, const char *name)
166 int no = 0;
167 int decpt, sign, res;
168 char buf [1024];
171 while (tests[no].value != -1.0)
173 res = efcvt_r (tests[no].value, tests[no].ndigit, &decpt, &sign,
174 buf, sizeof (buf));
175 if (res != 0
176 || decpt != tests[no].decpt
177 || sign != (tests[no].value < 0)
178 || strcmp (buf, tests[no].result) != 0)
179 output_r_error (name, tests[no].value, tests[no].ndigit,
180 tests[no].result, tests[no].decpt, 0,
181 (tests[no].value < 0),
182 buf, decpt, sign, res);
183 ++no;
187 static void
188 special (void)
190 int decpt, sign, res;
191 char *p;
192 char buf [1024];
194 p = ECVT (NAN, 10, &decpt, &sign);
195 if (sign != 0 || strcmp (p, "nan") != 0)
196 output_error (NAME (ECVT), NAN, 10, "nan", 0, 0, p, decpt, sign);
198 p = ECVT (INFINITY, 10, &decpt, &sign);
199 if (sign != 0 || strcmp (p, "inf") != 0)
200 output_error (NAME (ECVT), INFINITY, 10, "inf", 0, 0, p, decpt, sign);
202 /* Simply make sure these calls with large NDIGITs don't crash. */
203 p = ECVT (123.456, 10000, &decpt, &sign);
204 p = FCVT (123.456, 10000, &decpt, &sign);
206 /* Some tests for the reentrant functions. */
207 /* Use a too small buffer. */
208 res = ECVT_R (123.456, 10, &decpt, &sign, buf, 1);
209 if (res == 0)
211 printf (NAME (ECVT_R) " with a too small buffer was successful.\n");
212 support_record_failure ();
214 res = FCVT_R (123.456, 10, &decpt, &sign, buf, 1);
215 if (res == 0)
217 printf (NAME (FCVT_R) " with a too small buffer was successful.\n");
218 support_record_failure ();
223 static int
224 do_test (void)
226 test (ecvt_tests, ECVT, NAME (ECVT));
227 test (fcvt_tests, FCVT, NAME (FCVT));
228 test_r (ecvt_tests, ECVT_R, NAME (ECVT_R));
229 test_r (fcvt_tests, FCVT_R, NAME (FCVT_R));
230 special ();
232 return 0;
235 #include <support/test-driver.c>