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