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