1 //===-- Unittests for strtod ---------------------------------------------===// 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/FPUtil/FPBits.h" 10 #include "src/stdlib/strtod.h" 11 12 #include "utils/UnitTest/Test.h" 13 #include "utils/testutils/RoundingModeUtils.h" 14 15 #include <errno.h> 16 #include <limits.h> 17 #include <stddef.h> 18 19 using __llvm_libc::testutils::ForceRoundingModeTest; 20 using __llvm_libc::testutils::RoundingMode; 21 22 class LlvmLibcStrToDTest : public __llvm_libc::testing::Test, 23 ForceRoundingModeTest<RoundingMode::Nearest> { 24 public: 25 void run_test(const char *inputString, const ptrdiff_t expectedStrLen, 26 const uint64_t expectedRawData, const int expectedErrno = 0) { 27 // expectedRawData is the expected double result as a uint64_t, organized 28 // according to IEEE754: 29 // 30 // +-- 1 Sign Bit +-- 52 Mantissa bits 31 // | | 32 // | +-------------------------+------------------------+ 33 // | | | 34 // SEEEEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM 35 // | | 36 // +----+----+ 37 // | 38 // +-- 11 Exponent Bits 39 // 40 // This is so that the result can be compared in parts. 41 char *str_end = nullptr; 42 43 __llvm_libc::fputil::FPBits<double> expected_fp = 44 __llvm_libc::fputil::FPBits<double>(expectedRawData); 45 46 errno = 0; 47 double result = __llvm_libc::strtod(inputString, &str_end); 48 49 __llvm_libc::fputil::FPBits<double> actual_fp = 50 __llvm_libc::fputil::FPBits<double>(result); 51 52 EXPECT_EQ(str_end - inputString, expectedStrLen); 53 54 EXPECT_EQ(actual_fp.bits, expected_fp.bits); 55 EXPECT_EQ(actual_fp.get_sign(), expected_fp.get_sign()); 56 EXPECT_EQ(actual_fp.get_exponent(), expected_fp.get_exponent()); 57 EXPECT_EQ(actual_fp.get_mantissa(), expected_fp.get_mantissa()); 58 EXPECT_EQ(errno, expectedErrno); 59 } 60 }; 61 62 TEST_F(LlvmLibcStrToDTest, SimpleTest) { 63 run_test("123", 3, uint64_t(0x405ec00000000000)); 64 65 // This should fail on Eisel-Lemire, forcing a fallback to simple decimal 66 // conversion. 67 run_test("12345678901234549760", 20, uint64_t(0x43e56a95319d63d8)); 68 69 // Found while looking for difficult test cases here: 70 // https://github.com/nigeltao/parse-number-fxx-test-data/blob/main/more-test-cases/golang-org-issue-36657.txt 71 run_test("1090544144181609348835077142190", 31, uint64_t(0x462b8779f2474dfb)); 72 73 run_test("0x123", 5, uint64_t(0x4072300000000000)); 74 } 75 76 // These are tests that have caused problems in the past. 77 TEST_F(LlvmLibcStrToDTest, SpecificFailures) { 78 run_test("3E70000000000000", 16, uint64_t(0x7FF0000000000000), ERANGE); 79 run_test("358416272e-33", 13, uint64_t(0x3adbbb2a68c9d0b9)); 80 run_test("2.16656806400000023841857910156251e9", 36, 81 uint64_t(0x41e0246690000001)); 82 run_test("27949676547093071875", 20, uint64_t(0x43f83e132bc608c9)); 83 } 84 85 TEST_F(LlvmLibcStrToDTest, FuzzFailures) { 86 run_test("-\xff\xff\xff\xff\xff\xff\xff\x01", 0, uint64_t(0)); 87 run_test("-.????", 0, uint64_t(0)); 88 run_test( 89 "44444444444444444444444444444444444444444444444444A44444444444444444" 90 "44444444444*\x99\xff\xff\xff\xff", 91 50, uint64_t(0x4a3e68fdd0e0b2d8)); 92 run_test("-NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNKNNNNNNNNNNNNNNNNNN?" 93 "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN?", 94 0, uint64_t(0)); 95 run_test("0x.666E40", 9, uint64_t(0x3fd99b9000000000)); 96 } 97