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