| //===-- Unittests for strfromf --------------------------------------------===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "src/__support/FPUtil/FPBits.h" | |
| #include "src/__support/macros/properties/architectures.h" | |
| #include "src/stdlib/strfromf.h" | |
| #include "test/UnitTest/ErrnoCheckingTest.h" | |
| #include "test/UnitTest/ErrnoSetterMatcher.h" | |
| #include "test/UnitTest/Test.h" | |
| #define EXPECT_STREQ_LEN(str_size_needed, actual_str, expected_str) \ | |
| EXPECT_EQ(str_size_needed, static_cast<int>(sizeof(expected_str) - 1)); \ | |
| EXPECT_STREQ(actual_str, expected_str); | |
| using LlvmLibcStrfromfTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest; | |
| TEST_F(LlvmLibcStrfromfTest, DecimalFormat) { | |
| char buff[70]; | |
| int result; | |
| result = LIBC_NAMESPACE::strfromf(buff, 16, "%f", 1.0f); | |
| EXPECT_STREQ_LEN(result, buff, "1.000000"); | |
| result = LIBC_NAMESPACE::strfromf(buff, 20, "%f", 1234567890.0f); | |
| EXPECT_STREQ_LEN(result, buff, "1234567936.000000"); | |
| result = LIBC_NAMESPACE::strfromf(buff, 67, "%.3f", 1.0f); | |
| EXPECT_STREQ_LEN(result, buff, "1.000"); | |
| } | |
| TEST_F(LlvmLibcStrfromfTest, HexExponentFormat) { | |
| char buff[25]; | |
| int result; | |
| result = LIBC_NAMESPACE::strfromf(buff, 0, "%a", 1234567890.0f); | |
| EXPECT_EQ(result, 14); | |
| result = LIBC_NAMESPACE::strfromf(buff, 20, "%a", 1234567890.0f); | |
| EXPECT_EQ(result, 14); | |
| ASSERT_STREQ(buff, "0x1.26580cp+30"); | |
| result = LIBC_NAMESPACE::strfromf(buff, 20, "%A", 1234567890.0f); | |
| EXPECT_EQ(result, 14); | |
| ASSERT_STREQ(buff, "0X1.26580CP+30"); | |
| } | |
| TEST_F(LlvmLibcStrfromfTest, DecimalExponentFormat) { | |
| char buff[25]; | |
| int result; | |
| result = LIBC_NAMESPACE::strfromf(buff, 20, "%.9e", 1234567890.0f); | |
| EXPECT_STREQ_LEN(result, buff, "1.234567936e+09"); | |
| result = LIBC_NAMESPACE::strfromf(buff, 20, "%.9E", 1234567890.0f); | |
| EXPECT_STREQ_LEN(result, buff, "1.234567936E+09"); | |
| } | |
| TEST_F(LlvmLibcStrfromfTest, DecimalAutoFormat) { | |
| char buff[25]; | |
| int result; | |
| result = LIBC_NAMESPACE::strfromf(buff, 20, "%.9g", 1234567890.0f); | |
| EXPECT_STREQ_LEN(result, buff, "1.23456794e+09"); | |
| result = LIBC_NAMESPACE::strfromf(buff, 20, "%.9G", 1234567890.0f); | |
| EXPECT_STREQ_LEN(result, buff, "1.23456794E+09"); | |
| } | |
| TEST_F(LlvmLibcStrfromfTest, InsufficientBufferSize) { | |
| char buff[20]; | |
| int result; | |
| result = LIBC_NAMESPACE::strfromf(buff, 5, "%f", 1234567890.0f); | |
| EXPECT_EQ(result, 17); | |
| ASSERT_STREQ(buff, "1234"); | |
| result = LIBC_NAMESPACE::strfromf(buff, 5, "%.5f", 1.05f); | |
| EXPECT_EQ(result, 7); | |
| ASSERT_STREQ(buff, "1.05"); | |
| result = LIBC_NAMESPACE::strfromf(buff, 0, "%g", 1.0f); | |
| EXPECT_EQ(result, 1); | |
| ASSERT_STREQ(buff, "1.05"); // Make sure that buff has not changed | |
| } | |
| // TODO: fix https://github.com/llvm/llvm-project/issues/217708. | |
| #if 0 | |
| TEST_F(LlvmLibcStrfromfTest, InfNanValues) { | |
| char buff[15]; | |
| int result; | |
| float inf = LIBC_NAMESPACE::fputil::FPBits<float>::inf().get_val(); | |
| float nan = LIBC_NAMESPACE::fputil::FPBits<float>::quiet_nan().get_val(); | |
| result = LIBC_NAMESPACE::strfromf(buff, 10, "%f", inf); | |
| EXPECT_STREQ_LEN(result, buff, "inf"); | |
| result = LIBC_NAMESPACE::strfromf(buff, 10, "%A", -inf); | |
| EXPECT_STREQ_LEN(result, buff, "-INF"); | |
| result = LIBC_NAMESPACE::strfromf(buff, 10, "%f", nan); | |
| EXPECT_STREQ_LEN(result, buff, "nan"); | |
| result = LIBC_NAMESPACE::strfromf(buff, 10, "%A", -nan); | |
| EXPECT_STREQ_LEN(result, buff, "-NAN"); | |
| } | |
| #endif | |
| // https://github.com/llvm/llvm-project/issues/166795 | |
| TEST_F(LlvmLibcStrfromfTest, ResultOverflow) { | |
| #ifndef LIBC_TARGET_ARCH_IS_RISCV32 | |
| char buff[100]; | |
| // Trigger an overflow in the return value of strfromf by writing more than | |
| // INT_MAX bytes. | |
| int result = | |
| LIBC_NAMESPACE::strfromf(buff, sizeof(buff), "%.2147483647f", 1.0f); | |
| EXPECT_LT(result, 0); | |
| ASSERT_ERRNO_FAILURE(); | |
| #endif | |
| } |