1//===-- A template class for testing strfrom functions ----------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "src/__support/CPP/type_traits.h"
10#include "src/__support/FPUtil/FPBits.h"
11#include "test/UnitTest/Test.h"
12
13#define ASSERT_STREQ_LEN(actual_written, actual_str, expected_str) \
14 EXPECT_EQ(actual_written, static_cast<int>(sizeof(expected_str) - 1)); \
15 EXPECT_STREQ(actual_str, expected_str);
16
17template <typename InputT>
18class StrfromTest : public LIBC_NAMESPACE::testing::Test {
19
20 static const bool is_single_prec =
21 LIBC_NAMESPACE::cpp::is_same<InputT, float>::value;
22 static const bool is_double_prec =
23 LIBC_NAMESPACE::cpp::is_same<InputT, double>::value;
24
25 using FunctionT = int (*)(char *, size_t, const char *, InputT fp);
26
27public:
28 void floatDecimalFormat(FunctionT func) {
29 if (is_single_prec)
30 floatDecimalSinglePrec(func);
31 else if (is_double_prec)
32 floatDecimalDoublePrec(func);
33 else
34 floatDecimalLongDoublePrec(func);
35 }
36
37 void floatHexExpFormat(FunctionT func) {
38 if (is_single_prec)
39 floatHexExpSinglePrec(func);
40 else if (is_double_prec)
41 floatHexExpDoublePrec(func);
42 else
43 floatHexExpLongDoublePrec(func);
44 }
45
46 void floatDecimalExpFormat(FunctionT func) {
47 if (is_single_prec)
48 floatDecimalExpSinglePrec(func);
49 else if (is_double_prec)
50 floatDecimalExpDoublePrec(func);
51 else
52 floatDecimalExpLongDoublePrec(func);
53 }
54
55 void floatDecimalAutoFormat(FunctionT func) {
56 if (is_single_prec)
57 floatDecimalAutoSinglePrec(func);
58 else if (is_double_prec)
59 floatDecimalAutoDoublePrec(func);
60 else
61 floatDecimalAutoLongDoublePrec(func);
62 }
63
64 void improperFormatString(FunctionT func) {
65 char buff[100];
66 int written;
67 const bool is_long_double = !is_single_prec && !is_double_prec;
68
69 written = func(buff, 37, "A simple string with no conversions.", 1.0);
70 ASSERT_STREQ_LEN(written, buff, "A simple string with no conversions.");
71
72 written =
73 func(buff, 37,
74 "%A simple string with one conversion, should overwrite.", 1.0);
75 if (is_long_double) {
76#if defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80)
77 ASSERT_STREQ_LEN(written, buff, "0X8P-3");
78#elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64)
79 ASSERT_STREQ_LEN(written, buff, "0X1P+0");
80#elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128)
81 ASSERT_STREQ_LEN(written, buff, "0X1P+0");
82#endif
83 } else {
84 // not long double
85 ASSERT_STREQ_LEN(written, buff, "0X1P+0");
86 }
87 written = func(buff, 74,
88 "A simple string with one conversion in %A "
89 "between, writes string as it is",
90 1.0);
91 ASSERT_STREQ_LEN(written, buff,
92 "A simple string with one conversion in %A between, "
93 "writes string as it is");
94
95 written = func(buff, 36, "A simple string with one conversion", 1.0);
96 ASSERT_STREQ_LEN(written, buff, "A simple string with one conversion");
97
98 written = func(buff, 20, "%1f", 1234567890.0);
99 ASSERT_STREQ_LEN(written, buff, "%1f");
100 }
101
102 void insufficentBufsize(FunctionT func) {
103 char buff[20];
104 int written;
105
106 written = func(buff, 5, "%f", 1234567890.0);
107 EXPECT_EQ(written, 17);
108 ASSERT_STREQ(buff, "1234");
109
110 written = func(buff, 5, "%.5f", 1.05);
111 EXPECT_EQ(written, 7);
112 ASSERT_STREQ(buff, "1.05");
113
114 written = func(buff, 0, "%g", 1.0);
115 EXPECT_EQ(written, 1);
116 ASSERT_STREQ(buff, "1.05"); // Make sure that buff has not changed
117 }
118
119 void infNanValues(FunctionT func) {
120 if (is_double_prec)
121 doublePrecInfNan(func);
122 else if (!is_single_prec)
123 longDoublePrecInfNan(func);
124 }
125
126 void floatDecimalSinglePrec(FunctionT func) {
127 char buff[70];
128 int written;
129
130 written = func(buff, 16, "%f", 1.0);
131 ASSERT_STREQ_LEN(written, buff, "1.000000");
132
133 written = func(buff, 20, "%f", 1234567890.0);
134 ASSERT_STREQ_LEN(written, buff, "1234567936.000000");
135
136 written = func(buff, 67, "%.3f", 1.0);
137 ASSERT_STREQ_LEN(written, buff, "1.000");
138 }
139
140 void floatDecimalDoublePrec(FunctionT func) {
141 char buff[500];
142 int written;
143
144 written = func(buff, 99, "%f", 1.0);
145 ASSERT_STREQ_LEN(written, buff, "1.000000");
146
147 written = func(buff, 99, "%F", -1.0);
148 ASSERT_STREQ_LEN(written, buff, "-1.000000");
149
150 written = func(buff, 99, "%f", -1.234567);
151 ASSERT_STREQ_LEN(written, buff, "-1.234567");
152
153 written = func(buff, 99, "%f", 0.0);
154 ASSERT_STREQ_LEN(written, buff, "0.000000");
155
156 written = func(buff, 99, "%f", 1.5);
157 ASSERT_STREQ_LEN(written, buff, "1.500000");
158
159 written = func(buff, 499, "%f", 1e300);
160 ASSERT_STREQ_LEN(written, buff,
161 "100000000000000005250476025520442024870446858110815915491"
162 "585411551180245"
163 "798890819578637137508044786404370444383288387817694252323"
164 "536043057564479"
165 "218478670698284838720092657580373783023379478809005936895"
166 "323497079994508"
167 "111903896764088007465274278014249457925878882005684283811"
168 "566947219638686"
169 "5459400540160.000000");
170
171 written = func(buff, 99, "%f", 0.1);
172 ASSERT_STREQ_LEN(written, buff, "0.100000");
173
174 written = func(buff, 99, "%f", 1234567890123456789.0);
175 ASSERT_STREQ_LEN(written, buff, "1234567890123456768.000000");
176
177 written = func(buff, 99, "%f", 9999999999999.99);
178 ASSERT_STREQ_LEN(written, buff, "9999999999999.990234");
179
180 written = func(buff, 99, "%f", 0.1);
181 ASSERT_STREQ_LEN(written, buff, "0.100000");
182
183 written = func(buff, 99, "%f", 1234567890123456789.0);
184 ASSERT_STREQ_LEN(written, buff, "1234567890123456768.000000");
185
186 written = func(buff, 99, "%f", 9999999999999.99);
187 ASSERT_STREQ_LEN(written, buff, "9999999999999.990234");
188
189 // Precision Tests
190 written = func(buff, 100, "%.2f", 9999999999999.99);
191 ASSERT_STREQ_LEN(written, buff, "9999999999999.99");
192
193 written = func(buff, 100, "%.1f", 9999999999999.99);
194 ASSERT_STREQ_LEN(written, buff, "10000000000000.0");
195
196 written = func(buff, 100, "%.5f", 1.25);
197 ASSERT_STREQ_LEN(written, buff, "1.25000");
198
199 written = func(buff, 100, "%.0f", 1.25);
200 ASSERT_STREQ_LEN(written, buff, "1");
201
202 written = func(buff, 100, "%.20f", 1.234e-10);
203 ASSERT_STREQ_LEN(written, buff, "0.00000000012340000000");
204 }
205
206 void floatDecimalLongDoublePrec(FunctionT func) {
207 char buff[45];
208 int written;
209
210 written = func(buff, 40, "%f", 1.0L);
211 ASSERT_STREQ_LEN(written, buff, "1.000000");
212
213 written = func(buff, 10, "%.f", -2.5L);
214 ASSERT_STREQ_LEN(written, buff, "-2");
215 }
216
217 void floatHexExpSinglePrec(FunctionT func) {
218 char buff[25];
219 int written;
220
221 written = func(buff, 0, "%a", 1234567890.0);
222 EXPECT_EQ(written, 14);
223
224 written = func(buff, 20, "%a", 1234567890.0);
225 EXPECT_EQ(written, 14);
226 ASSERT_STREQ(buff, "0x1.26580cp+30");
227
228 written = func(buff, 20, "%A", 1234567890.0);
229 EXPECT_EQ(written, 14);
230 ASSERT_STREQ(buff, "0X1.26580CP+30");
231 }
232
233 void floatHexExpDoublePrec(FunctionT func) {
234 char buff[60];
235 int written;
236
237 written = func(buff, 10, "%a", 1.0);
238 ASSERT_STREQ_LEN(written, buff, "0x1p+0");
239
240 written = func(buff, 10, "%A", -1.0);
241 ASSERT_STREQ_LEN(written, buff, "-0X1P+0");
242
243 written = func(buff, 30, "%a", -0x1.abcdef12345p0);
244 ASSERT_STREQ_LEN(written, buff, "-0x1.abcdef12345p+0");
245
246 written = func(buff, 50, "%A", 0x1.abcdef12345p0);
247 ASSERT_STREQ_LEN(written, buff, "0X1.ABCDEF12345P+0");
248
249 written = func(buff, 10, "%a", 0.0);
250 ASSERT_STREQ_LEN(written, buff, "0x0p+0");
251
252 written = func(buff, 40, "%a", 1.0e100);
253 ASSERT_STREQ_LEN(written, buff, "0x1.249ad2594c37dp+332");
254
255 written = func(buff, 30, "%a", 0.1);
256 ASSERT_STREQ_LEN(written, buff, "0x1.999999999999ap-4");
257 }
258
259 void floatHexExpLongDoublePrec(FunctionT func) {
260 char buff[55];
261 int written;
262
263 written = func(buff, 50, "%a", 0.1L);
264#if defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80)
265 ASSERT_STREQ_LEN(written, buff, "0xc.ccccccccccccccdp-7");
266#elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64)
267 ASSERT_STREQ_LEN(written, buff, "0x1.999999999999ap-4");
268#elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128)
269 ASSERT_STREQ_LEN(written, buff, "0x1.999999999999999999999999999ap-4");
270#endif
271
272 written = func(buff, 20, "%.1a", 0.1L);
273#if defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80)
274 ASSERT_STREQ_LEN(written, buff, "0xc.dp-7");
275#elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64)
276 ASSERT_STREQ_LEN(written, buff, "0x1.ap-4");
277#elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128)
278 ASSERT_STREQ_LEN(written, buff, "0x1.ap-4");
279#endif
280
281 written = func(buff, 50, "%a", 1.0e1000L);
282#if defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80)
283 ASSERT_STREQ_LEN(written, buff, "0xf.38db1f9dd3dac05p+3318");
284#elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64)
285 ASSERT_STREQ_LEN(written, buff, "inf");
286#elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128)
287 ASSERT_STREQ_LEN(written, buff, "0x1.e71b63f3ba7b580af1a52d2a7379p+3321");
288#endif
289
290 written = func(buff, 50, "%a", 1.0e-1000L);
291#if defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80)
292 ASSERT_STREQ_LEN(written, buff, "0x8.68a9188a89e1467p-3325");
293#elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64)
294 ASSERT_STREQ_LEN(written, buff, "0x0p+0");
295#elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128)
296 ASSERT_STREQ_LEN(written, buff, "0x1.0d152311513c28ce202627c06ec2p-3322");
297#endif
298
299 written = func(buff, 50, "%.1a", 0xf.fffffffffffffffp16380L);
300#if defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80)
301 ASSERT_STREQ_LEN(written, buff, "0x1.0p+16384");
302#elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64)
303 ASSERT_STREQ_LEN(written, buff, "inf");
304#elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128)
305 ASSERT_STREQ_LEN(written, buff, "0x2.0p+16383");
306#endif
307 }
308
309 void floatDecimalExpSinglePrec(FunctionT func) {
310 char buff[25];
311 int written;
312
313 written = func(buff, 20, "%.9e", 1234567890.0);
314 ASSERT_STREQ_LEN(written, buff, "1.234567936e+09");
315
316 written = func(buff, 20, "%.9E", 1234567890.0);
317 ASSERT_STREQ_LEN(written, buff, "1.234567936E+09");
318 }
319
320 void floatDecimalExpDoublePrec(FunctionT func) {
321 char buff[101];
322 int written;
323
324 written = func(buff, 100, "%e", 1.0);
325 ASSERT_STREQ_LEN(written, buff, "1.000000e+00");
326
327 written = func(buff, 100, "%E", -1.0);
328 ASSERT_STREQ_LEN(written, buff, "-1.000000E+00");
329
330 written = func(buff, 100, "%e", -1.234567);
331 ASSERT_STREQ_LEN(written, buff, "-1.234567e+00");
332
333 written = func(buff, 100, "%e", 0.0);
334 ASSERT_STREQ_LEN(written, buff, "0.000000e+00");
335
336 written = func(buff, 100, "%e", 1.5);
337 ASSERT_STREQ_LEN(written, buff, "1.500000e+00");
338
339 written = func(buff, 100, "%e", 1e300);
340 ASSERT_STREQ_LEN(written, buff, "1.000000e+300");
341
342 written = func(buff, 100, "%e", 1234567890123456789.0);
343 ASSERT_STREQ_LEN(written, buff, "1.234568e+18");
344
345 // Precision Tests
346 written = func(buff, 100, "%.1e", 1.0);
347 ASSERT_STREQ_LEN(written, buff, "1.0e+00");
348
349 written = func(buff, 100, "%.1e", 1.99);
350 ASSERT_STREQ_LEN(written, buff, "2.0e+00");
351
352 written = func(buff, 100, "%.1e", 9.99);
353 ASSERT_STREQ_LEN(written, buff, "1.0e+01");
354 }
355
356 void floatDecimalExpLongDoublePrec(FunctionT func) {
357 // Mark as maybe_unused to silence unused variable
358 // warning when long double is not 80-bit
359 [[maybe_unused]] char buff[100];
360 [[maybe_unused]] int written;
361
362#if defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80)
363 written = func(buff, 90, "%.9e", 1000000000500000000.1L);
364 ASSERT_STREQ_LEN(written, buff, "1.000000001e+18");
365
366 written = func(buff, 90, "%.9e", 1000000000500000000.0L);
367 ASSERT_STREQ_LEN(written, buff, "1.000000000e+18");
368
369 written = func(buff, 90, "%e", 0xf.fffffffffffffffp+16380L);
370 ASSERT_STREQ_LEN(written, buff, "1.189731e+4932");
371#endif // LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80
372 }
373
374 void floatDecimalAutoSinglePrec(FunctionT func) {
375 char buff[25];
376 int written;
377
378 written = func(buff, 20, "%.9g", 1234567890.0);
379 ASSERT_STREQ_LEN(written, buff, "1.23456794e+09");
380
381 written = func(buff, 20, "%.9G", 1234567890.0);
382 ASSERT_STREQ_LEN(written, buff, "1.23456794E+09");
383 }
384
385 void floatDecimalAutoDoublePrec(FunctionT func) {
386 char buff[120];
387 int written;
388
389 written = func(buff, 100, "%g", 1234567890123456789.0);
390 ASSERT_STREQ_LEN(written, buff, "1.23457e+18");
391
392 written = func(buff, 100, "%g", 9999990000000.00);
393 ASSERT_STREQ_LEN(written, buff, "9.99999e+12");
394
395 written = func(buff, 100, "%g", 9999999000000.00);
396 ASSERT_STREQ_LEN(written, buff, "1e+13");
397
398 written = func(buff, 100, "%g", 0xa.aaaaaaaaaaaaaabp-7);
399 ASSERT_STREQ_LEN(written, buff, "0.0833333");
400
401 written = func(buff, 100, "%g", 0.00001);
402 ASSERT_STREQ_LEN(written, buff, "1e-05");
403
404 // Precision Tests
405 written = func(buff, 100, "%.0g", 0.0);
406 ASSERT_STREQ_LEN(written, buff, "0");
407
408 written = func(buff, 100, "%.2g", 0.1);
409 ASSERT_STREQ_LEN(written, buff, "0.1");
410
411 written = func(buff, 100, "%.2g", 1.09);
412 ASSERT_STREQ_LEN(written, buff, "1.1");
413
414 written = func(buff, 100, "%.15g", 22.25);
415 ASSERT_STREQ_LEN(written, buff, "22.25");
416
417 written = func(buff, 100, "%.20g", 1.234e-10);
418 ASSERT_STREQ_LEN(written, buff, "1.2340000000000000814e-10");
419 }
420
421 void floatDecimalAutoLongDoublePrec(FunctionT func) {
422 // Mark as maybe_unused to silence unused variable
423 // warning when long double is not 80-bit
424 [[maybe_unused]] char buff[100];
425 [[maybe_unused]] int written;
426
427#if defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80)
428 written = func(buff, 99, "%g", 0xf.fffffffffffffffp+16380L);
429 ASSERT_STREQ_LEN(written, buff, "1.18973e+4932");
430
431 written = func(buff, 99, "%g", 0xa.aaaaaaaaaaaaaabp-7L);
432 ASSERT_STREQ_LEN(written, buff, "0.0833333");
433
434 written = func(buff, 99, "%g", 9.99999999999e-100L);
435 ASSERT_STREQ_LEN(written, buff, "1e-99");
436#endif // LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80
437 }
438
439 void doublePrecInfNan(FunctionT func) {
440 char buff[15];
441 int written;
442
443 double inf = LIBC_NAMESPACE::fputil::FPBits<double>::inf().get_val();
444 double nan = LIBC_NAMESPACE::fputil::FPBits<double>::quiet_nan().get_val();
445
446 written = func(buff, 10, "%f", inf);
447 ASSERT_STREQ_LEN(written, buff, "inf");
448
449 written = func(buff, 10, "%A", -inf);
450 ASSERT_STREQ_LEN(written, buff, "-INF");
451
452 written = func(buff, 10, "%f", nan);
453 ASSERT_STREQ_LEN(written, buff, "nan");
454
455 written = func(buff, 10, "%A", -nan);
456 ASSERT_STREQ_LEN(written, buff, "-NAN");
457 }
458
459 void longDoublePrecInfNan(FunctionT func) {
460 char buff[15];
461 int written;
462
463 long double ld_inf =
464 LIBC_NAMESPACE::fputil::FPBits<long double>::inf().get_val();
465 long double ld_nan =
466 LIBC_NAMESPACE::fputil::FPBits<long double>::quiet_nan().get_val();
467
468 written = func(buff, 10, "%f", ld_inf);
469 ASSERT_STREQ_LEN(written, buff, "inf");
470
471 written = func(buff, 10, "%A", -ld_inf);
472 ASSERT_STREQ_LEN(written, buff, "-INF");
473
474 written = func(buff, 10, "%f", ld_nan);
475 ASSERT_STREQ_LEN(written, buff, "nan");
476
477 written = func(buff, 10, "%A", -ld_nan);
478 ASSERT_STREQ_LEN(written, buff, "-NAN");
479 }
480};
481
482#define STRFROM_TEST(InputType, name, func) \
483 using LlvmLibc##name##Test = StrfromTest<InputType>; \
484 TEST_F(LlvmLibc##name##Test, FloatDecimalFormat) { \
485 floatDecimalFormat(func); \
486 } \
487 TEST_F(LlvmLibc##name##Test, FloatHexExpFormat) { floatHexExpFormat(func); } \
488 TEST_F(LlvmLibc##name##Test, FloatDecimalAutoFormat) { \
489 floatDecimalAutoFormat(func); \
490 } \
491 TEST_F(LlvmLibc##name##Test, FloatDecimalExpFormat) { \
492 floatDecimalExpFormat(func); \
493 } \
494 TEST_F(LlvmLibc##name##Test, ImproperFormatString) { \
495 improperFormatString(func); \
496 } \
497 TEST_F(LlvmLibc##name##Test, InsufficientBufferSize) { \
498 insufficentBufsize(func); \
499 } \
500 TEST_F(LlvmLibc##name##Test, InfAndNanValues) { infNanValues(func); }
501

source code of libc/test/src/stdlib/StrfromTest.h