xref: /aosp_15_r20/external/llvm-libc/test/src/stdlib/StrfromTest.h (revision 71db0c75aadcf003ffe3238005f61d7618a3fead)
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 
17 template <typename InputT>
18 class 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 
27 public:
floatDecimalFormat(FunctionT func)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 
floatHexExpFormat(FunctionT func)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 
floatDecimalExpFormat(FunctionT func)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 
floatDecimalAutoFormat(FunctionT func)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 
improperFormatString(FunctionT func)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 
insufficentBufsize(FunctionT func)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 
infNanValues(FunctionT func)119   void infNanValues(FunctionT func) {
120     if (is_double_prec)
121       doublePrecInfNan(func);
122     else if (!is_single_prec)
123       longDoublePrecInfNan(func);
124   }
125 
floatDecimalSinglePrec(FunctionT func)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 
floatDecimalDoublePrec(FunctionT func)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 // Dyadic float is only accurate to ~50 digits, so skip this 300 digit test.
160 // TODO: Create way to test just the first ~50 digits of a number.
161 #ifndef LIBC_COPT_FLOAT_TO_STR_REDUCED_PRECISION
162     written = func(buff, 499, "%f", 1e300);
163     ASSERT_STREQ_LEN(written, buff,
164                      "100000000000000005250476025520442024870446858110815915491"
165                      "585411551180245"
166                      "798890819578637137508044786404370444383288387817694252323"
167                      "536043057564479"
168                      "218478670698284838720092657580373783023379478809005936895"
169                      "323497079994508"
170                      "111903896764088007465274278014249457925878882005684283811"
171                      "566947219638686"
172                      "5459400540160.000000");
173 #endif // DLIBC_COPT_FLOAT_TO_STR_REDUCED_PRECISION
174 
175     written = func(buff, 99, "%f", 0.1);
176     ASSERT_STREQ_LEN(written, buff, "0.100000");
177 
178     written = func(buff, 99, "%f", 1234567890123456789.0);
179     ASSERT_STREQ_LEN(written, buff, "1234567890123456768.000000");
180 
181     written = func(buff, 99, "%f", 9999999999999.99);
182     ASSERT_STREQ_LEN(written, buff, "9999999999999.990234");
183 
184     written = func(buff, 99, "%f", 0.1);
185     ASSERT_STREQ_LEN(written, buff, "0.100000");
186 
187     written = func(buff, 99, "%f", 1234567890123456789.0);
188     ASSERT_STREQ_LEN(written, buff, "1234567890123456768.000000");
189 
190     written = func(buff, 99, "%f", 9999999999999.99);
191     ASSERT_STREQ_LEN(written, buff, "9999999999999.990234");
192 
193     // Precision Tests
194     written = func(buff, 100, "%.2f", 9999999999999.99);
195     ASSERT_STREQ_LEN(written, buff, "9999999999999.99");
196 
197     written = func(buff, 100, "%.1f", 9999999999999.99);
198     ASSERT_STREQ_LEN(written, buff, "10000000000000.0");
199 
200     written = func(buff, 100, "%.5f", 1.25);
201     ASSERT_STREQ_LEN(written, buff, "1.25000");
202 
203     written = func(buff, 100, "%.0f", 1.25);
204     ASSERT_STREQ_LEN(written, buff, "1");
205 
206     written = func(buff, 100, "%.20f", 1.234e-10);
207     ASSERT_STREQ_LEN(written, buff, "0.00000000012340000000");
208   }
209 
floatDecimalLongDoublePrec(FunctionT func)210   void floatDecimalLongDoublePrec(FunctionT func) {
211     char buff[45];
212     int written;
213 
214     written = func(buff, 40, "%f", 1.0L);
215     ASSERT_STREQ_LEN(written, buff, "1.000000");
216 
217     written = func(buff, 10, "%.f", -2.5L);
218     ASSERT_STREQ_LEN(written, buff, "-2");
219   }
220 
floatHexExpSinglePrec(FunctionT func)221   void floatHexExpSinglePrec(FunctionT func) {
222     char buff[25];
223     int written;
224 
225     written = func(buff, 0, "%a", 1234567890.0);
226     EXPECT_EQ(written, 14);
227 
228     written = func(buff, 20, "%a", 1234567890.0);
229     EXPECT_EQ(written, 14);
230     ASSERT_STREQ(buff, "0x1.26580cp+30");
231 
232     written = func(buff, 20, "%A", 1234567890.0);
233     EXPECT_EQ(written, 14);
234     ASSERT_STREQ(buff, "0X1.26580CP+30");
235   }
236 
floatHexExpDoublePrec(FunctionT func)237   void floatHexExpDoublePrec(FunctionT func) {
238     char buff[60];
239     int written;
240 
241     written = func(buff, 10, "%a", 1.0);
242     ASSERT_STREQ_LEN(written, buff, "0x1p+0");
243 
244     written = func(buff, 10, "%A", -1.0);
245     ASSERT_STREQ_LEN(written, buff, "-0X1P+0");
246 
247     written = func(buff, 30, "%a", -0x1.abcdef12345p0);
248     ASSERT_STREQ_LEN(written, buff, "-0x1.abcdef12345p+0");
249 
250     written = func(buff, 50, "%A", 0x1.abcdef12345p0);
251     ASSERT_STREQ_LEN(written, buff, "0X1.ABCDEF12345P+0");
252 
253     written = func(buff, 10, "%a", 0.0);
254     ASSERT_STREQ_LEN(written, buff, "0x0p+0");
255 
256     written = func(buff, 40, "%a", 1.0e100);
257     ASSERT_STREQ_LEN(written, buff, "0x1.249ad2594c37dp+332");
258 
259     written = func(buff, 30, "%a", 0.1);
260     ASSERT_STREQ_LEN(written, buff, "0x1.999999999999ap-4");
261   }
262 
floatHexExpLongDoublePrec(FunctionT func)263   void floatHexExpLongDoublePrec(FunctionT func) {
264     char buff[55];
265     int written;
266 
267     written = func(buff, 50, "%a", 0.1L);
268 #if defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80)
269     ASSERT_STREQ_LEN(written, buff, "0xc.ccccccccccccccdp-7");
270 #elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64)
271     ASSERT_STREQ_LEN(written, buff, "0x1.999999999999ap-4");
272 #elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128)
273     ASSERT_STREQ_LEN(written, buff, "0x1.999999999999999999999999999ap-4");
274 #endif
275 
276     written = func(buff, 20, "%.1a", 0.1L);
277 #if defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80)
278     ASSERT_STREQ_LEN(written, buff, "0xc.dp-7");
279 #elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64)
280     ASSERT_STREQ_LEN(written, buff, "0x1.ap-4");
281 #elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128)
282     ASSERT_STREQ_LEN(written, buff, "0x1.ap-4");
283 #endif
284 
285     written = func(buff, 50, "%a", 1.0e1000L);
286 #if defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80)
287     ASSERT_STREQ_LEN(written, buff, "0xf.38db1f9dd3dac05p+3318");
288 #elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64)
289     ASSERT_STREQ_LEN(written, buff, "inf");
290 #elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128)
291     ASSERT_STREQ_LEN(written, buff, "0x1.e71b63f3ba7b580af1a52d2a7379p+3321");
292 #endif
293 
294     written = func(buff, 50, "%a", 1.0e-1000L);
295 #if defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80)
296     ASSERT_STREQ_LEN(written, buff, "0x8.68a9188a89e1467p-3325");
297 #elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64)
298     ASSERT_STREQ_LEN(written, buff, "0x0p+0");
299 #elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128)
300     ASSERT_STREQ_LEN(written, buff, "0x1.0d152311513c28ce202627c06ec2p-3322");
301 #endif
302 
303     written = func(buff, 50, "%.1a", 0xf.fffffffffffffffp16380L);
304 #if defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80)
305     ASSERT_STREQ_LEN(written, buff, "0x1.0p+16384");
306 #elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64)
307     ASSERT_STREQ_LEN(written, buff, "inf");
308 #elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128)
309     ASSERT_STREQ_LEN(written, buff, "0x2.0p+16383");
310 #endif
311   }
312 
floatDecimalExpSinglePrec(FunctionT func)313   void floatDecimalExpSinglePrec(FunctionT func) {
314     char buff[25];
315     int written;
316 
317     written = func(buff, 20, "%.9e", 1234567890.0);
318     ASSERT_STREQ_LEN(written, buff, "1.234567936e+09");
319 
320     written = func(buff, 20, "%.9E", 1234567890.0);
321     ASSERT_STREQ_LEN(written, buff, "1.234567936E+09");
322   }
323 
floatDecimalExpDoublePrec(FunctionT func)324   void floatDecimalExpDoublePrec(FunctionT func) {
325     char buff[101];
326     int written;
327 
328     written = func(buff, 100, "%e", 1.0);
329     ASSERT_STREQ_LEN(written, buff, "1.000000e+00");
330 
331     written = func(buff, 100, "%E", -1.0);
332     ASSERT_STREQ_LEN(written, buff, "-1.000000E+00");
333 
334     written = func(buff, 100, "%e", -1.234567);
335     ASSERT_STREQ_LEN(written, buff, "-1.234567e+00");
336 
337     written = func(buff, 100, "%e", 0.0);
338     ASSERT_STREQ_LEN(written, buff, "0.000000e+00");
339 
340     written = func(buff, 100, "%e", 1.5);
341     ASSERT_STREQ_LEN(written, buff, "1.500000e+00");
342 
343     written = func(buff, 100, "%e", 1e300);
344     ASSERT_STREQ_LEN(written, buff, "1.000000e+300");
345 
346     written = func(buff, 100, "%e", 1234567890123456789.0);
347     ASSERT_STREQ_LEN(written, buff, "1.234568e+18");
348 
349     // Precision Tests
350     written = func(buff, 100, "%.1e", 1.0);
351     ASSERT_STREQ_LEN(written, buff, "1.0e+00");
352 
353     written = func(buff, 100, "%.1e", 1.99);
354     ASSERT_STREQ_LEN(written, buff, "2.0e+00");
355 
356     written = func(buff, 100, "%.1e", 9.99);
357     ASSERT_STREQ_LEN(written, buff, "1.0e+01");
358   }
359 
floatDecimalExpLongDoublePrec(FunctionT func)360   void floatDecimalExpLongDoublePrec(FunctionT func) {
361     // Mark as maybe_unused to silence unused variable
362     // warning when long double is not 80-bit
363     [[maybe_unused]] char buff[100];
364     [[maybe_unused]] int written;
365 
366 #if defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80)
367     written = func(buff, 90, "%.9e", 1000000000500000000.1L);
368     ASSERT_STREQ_LEN(written, buff, "1.000000001e+18");
369 
370     written = func(buff, 90, "%.9e", 1000000000500000000.0L);
371     ASSERT_STREQ_LEN(written, buff, "1.000000000e+18");
372 
373     written = func(buff, 90, "%e", 0xf.fffffffffffffffp+16380L);
374     ASSERT_STREQ_LEN(written, buff, "1.189731e+4932");
375 #endif // LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80
376   }
377 
floatDecimalAutoSinglePrec(FunctionT func)378   void floatDecimalAutoSinglePrec(FunctionT func) {
379     char buff[25];
380     int written;
381 
382     written = func(buff, 20, "%.9g", 1234567890.0);
383     ASSERT_STREQ_LEN(written, buff, "1.23456794e+09");
384 
385     written = func(buff, 20, "%.9G", 1234567890.0);
386     ASSERT_STREQ_LEN(written, buff, "1.23456794E+09");
387   }
388 
floatDecimalAutoDoublePrec(FunctionT func)389   void floatDecimalAutoDoublePrec(FunctionT func) {
390     char buff[120];
391     int written;
392 
393     written = func(buff, 100, "%g", 1234567890123456789.0);
394     ASSERT_STREQ_LEN(written, buff, "1.23457e+18");
395 
396     written = func(buff, 100, "%g", 9999990000000.00);
397     ASSERT_STREQ_LEN(written, buff, "9.99999e+12");
398 
399     written = func(buff, 100, "%g", 9999999000000.00);
400     ASSERT_STREQ_LEN(written, buff, "1e+13");
401 
402     written = func(buff, 100, "%g", 0xa.aaaaaaaaaaaaaabp-7);
403     ASSERT_STREQ_LEN(written, buff, "0.0833333");
404 
405     written = func(buff, 100, "%g", 0.00001);
406     ASSERT_STREQ_LEN(written, buff, "1e-05");
407 
408     // Precision Tests
409     written = func(buff, 100, "%.0g", 0.0);
410     ASSERT_STREQ_LEN(written, buff, "0");
411 
412     written = func(buff, 100, "%.2g", 0.1);
413     ASSERT_STREQ_LEN(written, buff, "0.1");
414 
415     written = func(buff, 100, "%.2g", 1.09);
416     ASSERT_STREQ_LEN(written, buff, "1.1");
417 
418     written = func(buff, 100, "%.15g", 22.25);
419     ASSERT_STREQ_LEN(written, buff, "22.25");
420 
421     written = func(buff, 100, "%.20g", 1.234e-10);
422     ASSERT_STREQ_LEN(written, buff, "1.2340000000000000814e-10");
423   }
424 
floatDecimalAutoLongDoublePrec(FunctionT func)425   void floatDecimalAutoLongDoublePrec(FunctionT func) {
426     // Mark as maybe_unused to silence unused variable
427     // warning when long double is not 80-bit
428     [[maybe_unused]] char buff[100];
429     [[maybe_unused]] int written;
430 
431 #if defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80)
432     written = func(buff, 99, "%g", 0xf.fffffffffffffffp+16380L);
433     ASSERT_STREQ_LEN(written, buff, "1.18973e+4932");
434 
435     written = func(buff, 99, "%g", 0xa.aaaaaaaaaaaaaabp-7L);
436     ASSERT_STREQ_LEN(written, buff, "0.0833333");
437 
438     written = func(buff, 99, "%g", 9.99999999999e-100L);
439     ASSERT_STREQ_LEN(written, buff, "1e-99");
440 #endif // LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80
441   }
442 
doublePrecInfNan(FunctionT func)443   void doublePrecInfNan(FunctionT func) {
444     char buff[15];
445     int written;
446 
447     double inf = LIBC_NAMESPACE::fputil::FPBits<double>::inf().get_val();
448     double nan = LIBC_NAMESPACE::fputil::FPBits<double>::quiet_nan().get_val();
449 
450     written = func(buff, 10, "%f", inf);
451     ASSERT_STREQ_LEN(written, buff, "inf");
452 
453     written = func(buff, 10, "%A", -inf);
454     ASSERT_STREQ_LEN(written, buff, "-INF");
455 
456     written = func(buff, 10, "%f", nan);
457     ASSERT_STREQ_LEN(written, buff, "nan");
458 
459     written = func(buff, 10, "%A", -nan);
460     ASSERT_STREQ_LEN(written, buff, "-NAN");
461   }
462 
longDoublePrecInfNan(FunctionT func)463   void longDoublePrecInfNan(FunctionT func) {
464     char buff[15];
465     int written;
466 
467     long double ld_inf =
468         LIBC_NAMESPACE::fputil::FPBits<long double>::inf().get_val();
469     long double ld_nan =
470         LIBC_NAMESPACE::fputil::FPBits<long double>::quiet_nan().get_val();
471 
472     written = func(buff, 10, "%f", ld_inf);
473     ASSERT_STREQ_LEN(written, buff, "inf");
474 
475     written = func(buff, 10, "%A", -ld_inf);
476     ASSERT_STREQ_LEN(written, buff, "-INF");
477 
478     written = func(buff, 10, "%f", ld_nan);
479     ASSERT_STREQ_LEN(written, buff, "nan");
480 
481     written = func(buff, 10, "%A", -ld_nan);
482     ASSERT_STREQ_LEN(written, buff, "-NAN");
483   }
484 };
485 
486 #define STRFROM_TEST(InputType, name, func)                                    \
487   using LlvmLibc##name##Test = StrfromTest<InputType>;                         \
488   TEST_F(LlvmLibc##name##Test, FloatDecimalFormat) {                           \
489     floatDecimalFormat(func);                                                  \
490   }                                                                            \
491   TEST_F(LlvmLibc##name##Test, FloatHexExpFormat) { floatHexExpFormat(func); } \
492   TEST_F(LlvmLibc##name##Test, FloatDecimalAutoFormat) {                       \
493     floatDecimalAutoFormat(func);                                              \
494   }                                                                            \
495   TEST_F(LlvmLibc##name##Test, FloatDecimalExpFormat) {                        \
496     floatDecimalExpFormat(func);                                               \
497   }                                                                            \
498   TEST_F(LlvmLibc##name##Test, ImproperFormatString) {                         \
499     improperFormatString(func);                                                \
500   }                                                                            \
501   TEST_F(LlvmLibc##name##Test, InsufficientBufferSize) {                       \
502     insufficentBufsize(func);                                                  \
503   }                                                                            \
504   TEST_F(LlvmLibc##name##Test, InfAndNanValues) { infNanValues(func); }
505