• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     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 
floatDecimalLongDoublePrec(FunctionT func)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 
floatHexExpSinglePrec(FunctionT func)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 
floatHexExpDoublePrec(FunctionT func)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 
floatHexExpLongDoublePrec(FunctionT func)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 
floatDecimalExpSinglePrec(FunctionT func)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 
floatDecimalExpDoublePrec(FunctionT func)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 
floatDecimalExpLongDoublePrec(FunctionT func)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 
floatDecimalAutoSinglePrec(FunctionT func)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 
floatDecimalAutoDoublePrec(FunctionT func)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 
floatDecimalAutoLongDoublePrec(FunctionT func)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 
doublePrecInfNan(FunctionT func)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 
longDoublePrecInfNan(FunctionT func)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