mirror of
https://github.com/SerenityOS/serenity.git
synced 2026-11-08 17:49:04 -10:00
128 lines
3.8 KiB
C++
128 lines
3.8 KiB
C++
/*
|
|
* Copyright (c) 2025, Tomás Simões <[email protected]>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include <AK/FloatingPointStringConversions.h>
|
|
#include <AK/Math/Constants.h>
|
|
#include <AK/UFixedBigInt.h>
|
|
#include <LibTest/TestCase.h>
|
|
|
|
using namespace AK;
|
|
|
|
enum class ParserType {
|
|
Regular,
|
|
Hexfloat,
|
|
Complete
|
|
};
|
|
|
|
struct FloatingPointTestCase {
|
|
StringView input;
|
|
double expected_value;
|
|
FloatingPointError expected_error;
|
|
int expected_end_offset;
|
|
ParserType parser_type;
|
|
};
|
|
|
|
static void floating_point_parsing_helper(FloatingPointTestCase const& test_case)
|
|
{
|
|
auto const* input = test_case.input.characters_without_null_termination();
|
|
size_t const input_length = test_case.input.length();
|
|
|
|
switch (test_case.parser_type) {
|
|
case ParserType::Regular: {
|
|
auto result = parse_first_floating_point<double>(input, input + input_length);
|
|
EXPECT_EQ(result.error, test_case.expected_error);
|
|
// If the error is NoOrInvalidInput, parse_first_floating_point might return NaN/null
|
|
if (test_case.expected_error != FloatingPointError::NoOrInvalidInput) {
|
|
EXPECT_EQ(result.value, test_case.expected_value);
|
|
EXPECT_EQ(result.end_ptr, input + test_case.expected_end_offset);
|
|
}
|
|
break;
|
|
}
|
|
case ParserType::Hexfloat: {
|
|
auto result = parse_first_hexfloat_until_zero_character<double>(input);
|
|
EXPECT_EQ(result.error, test_case.expected_error);
|
|
EXPECT_EQ(result.value, test_case.expected_value);
|
|
EXPECT_EQ(result.end_ptr, input + test_case.expected_end_offset);
|
|
break;
|
|
}
|
|
case ParserType::Complete: {
|
|
auto result = parse_floating_point_completely<double>(input, input + input_length);
|
|
if (test_case.expected_error == FloatingPointError::None) {
|
|
EXPECT(result.has_value());
|
|
EXPECT_EQ(result.value(), test_case.expected_value);
|
|
} else {
|
|
EXPECT(!result.has_value());
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_CASE(basic_integer)
|
|
{
|
|
floating_point_parsing_helper({ "123"sv, 123.0, FloatingPointError::None, 3, ParserType::Regular });
|
|
}
|
|
|
|
TEST_CASE(decimal_number)
|
|
{
|
|
floating_point_parsing_helper({ "123.45"sv, 123.45, FloatingPointError::None, 6, ParserType::Regular });
|
|
}
|
|
|
|
TEST_CASE(exponent_notation)
|
|
{
|
|
floating_point_parsing_helper({ "1.5e3"sv, 1500.0, FloatingPointError::None, 5, ParserType::Regular });
|
|
}
|
|
|
|
TEST_CASE(negative_number)
|
|
{
|
|
floating_point_parsing_helper({ "-67.89"sv, -67.89, FloatingPointError::None, 6, ParserType::Regular });
|
|
}
|
|
|
|
TEST_CASE(zero)
|
|
{
|
|
floating_point_parsing_helper({ "0"sv, 0.0, FloatingPointError::None, 1, ParserType::Regular });
|
|
}
|
|
|
|
TEST_CASE(negative_zero)
|
|
{
|
|
floating_point_parsing_helper({ "-0.0"sv, -0.0, FloatingPointError::None, 4, ParserType::Regular });
|
|
}
|
|
|
|
TEST_CASE(invalid_input)
|
|
{
|
|
floating_point_parsing_helper({ "abc"sv, 0.0, FloatingPointError::NoOrInvalidInput, 0, ParserType::Regular });
|
|
}
|
|
|
|
TEST_CASE(partial_parse)
|
|
{
|
|
floating_point_parsing_helper({ "123.45abc"sv, 123.45, FloatingPointError::None, 6, ParserType::Regular });
|
|
}
|
|
|
|
TEST_CASE(hex_float)
|
|
{
|
|
floating_point_parsing_helper({ "0x1.8p1"sv, 3.0, FloatingPointError::None, 7, ParserType::Hexfloat });
|
|
}
|
|
|
|
TEST_CASE(out_of_range)
|
|
{
|
|
floating_point_parsing_helper({ "1e309"sv, AK::Infinity<double>, FloatingPointError::OutOfRange, 5, ParserType::Regular });
|
|
}
|
|
|
|
TEST_CASE(rounded_down_to_zero)
|
|
{
|
|
floating_point_parsing_helper({ "1e-400"sv, 0.0, FloatingPointError::RoundedDownToZero, 6, ParserType::Regular });
|
|
}
|
|
|
|
TEST_CASE(parse_completely_valid)
|
|
{
|
|
floating_point_parsing_helper({ "123.45"sv, 123.45, FloatingPointError::None, 0, ParserType::Complete });
|
|
}
|
|
|
|
TEST_CASE(parse_completely_invalid)
|
|
{
|
|
floating_point_parsing_helper({ "123.45a"sv, 0.0, FloatingPointError::NoOrInvalidInput, 0, ParserType::Complete });
|
|
}
|