blob: 5baeb119bf1501678895b72b638c8390e7295ead [file]
//===-- 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
}