#include #include "utils/parse_int.hpp" namespace devilution { TEST(ParseIntTest, ParseInt) { ParseIntResult result = ParseInt(""); ASSERT_FALSE(result.has_value()); EXPECT_EQ(result.error(), ParseIntError::ParseError); result = ParseInt("abcd"); ASSERT_FALSE(result.has_value()); EXPECT_EQ(result.error(), ParseIntError::ParseError); result = ParseInt("12"); ASSERT_TRUE(result.has_value()); EXPECT_EQ(result.value(), 12); result = ParseInt(("99999999"), -5, 100); ASSERT_FALSE(result.has_value()); EXPECT_EQ(result.error(), ParseIntError::OutOfRange); ParseIntResult shortResult = ParseInt(("99999999")); ASSERT_FALSE(shortResult.has_value()); EXPECT_EQ(shortResult.error(), ParseIntError::OutOfRange); } TEST(ParseIntTest, ParseFixed6Fraction) { EXPECT_EQ(ParseFixed6Fraction(""), 0); EXPECT_EQ(ParseFixed6Fraction("0"), 0); EXPECT_EQ(ParseFixed6Fraction("00781249"), 0); EXPECT_EQ(ParseFixed6Fraction("0078125"), 1); EXPECT_EQ(ParseFixed6Fraction("015625"), 1); EXPECT_EQ(ParseFixed6Fraction("03125"), 2); EXPECT_EQ(ParseFixed6Fraction("046875"), 3); EXPECT_EQ(ParseFixed6Fraction("0625"), 4); EXPECT_EQ(ParseFixed6Fraction("078125"), 5); EXPECT_EQ(ParseFixed6Fraction("09375"), 6); EXPECT_EQ(ParseFixed6Fraction("109375"), 7); EXPECT_EQ(ParseFixed6Fraction("125"), 8); EXPECT_EQ(ParseFixed6Fraction("140625"), 9); EXPECT_EQ(ParseFixed6Fraction("15625"), 10); EXPECT_EQ(ParseFixed6Fraction("171875"), 11); EXPECT_EQ(ParseFixed6Fraction("1875"), 12); EXPECT_EQ(ParseFixed6Fraction("203125"), 13); EXPECT_EQ(ParseFixed6Fraction("21875"), 14); EXPECT_EQ(ParseFixed6Fraction("234375"), 15); EXPECT_EQ(ParseFixed6Fraction("25"), 16); EXPECT_EQ(ParseFixed6Fraction("265625"), 17); EXPECT_EQ(ParseFixed6Fraction("28125"), 18); EXPECT_EQ(ParseFixed6Fraction("296875"), 19); EXPECT_EQ(ParseFixed6Fraction("3125"), 20); EXPECT_EQ(ParseFixed6Fraction("328125"), 21); EXPECT_EQ(ParseFixed6Fraction("34375"), 22); EXPECT_EQ(ParseFixed6Fraction("359375"), 23); EXPECT_EQ(ParseFixed6Fraction("375"), 24); EXPECT_EQ(ParseFixed6Fraction("390625"), 25); EXPECT_EQ(ParseFixed6Fraction("40625"), 26); EXPECT_EQ(ParseFixed6Fraction("421875"), 27); EXPECT_EQ(ParseFixed6Fraction("4375"), 28); EXPECT_EQ(ParseFixed6Fraction("453125"), 29); EXPECT_EQ(ParseFixed6Fraction("46875"), 30); EXPECT_EQ(ParseFixed6Fraction("484375"), 31); EXPECT_EQ(ParseFixed6Fraction("5"), 32); EXPECT_EQ(ParseFixed6Fraction("515625"), 33); EXPECT_EQ(ParseFixed6Fraction("53125"), 34); EXPECT_EQ(ParseFixed6Fraction("546875"), 35); EXPECT_EQ(ParseFixed6Fraction("5625"), 36); EXPECT_EQ(ParseFixed6Fraction("578125"), 37); EXPECT_EQ(ParseFixed6Fraction("59375"), 38); EXPECT_EQ(ParseFixed6Fraction("609375"), 39); EXPECT_EQ(ParseFixed6Fraction("625"), 40); EXPECT_EQ(ParseFixed6Fraction("640625"), 41); EXPECT_EQ(ParseFixed6Fraction("65625"), 42); EXPECT_EQ(ParseFixed6Fraction("671875"), 43); EXPECT_EQ(ParseFixed6Fraction("6875"), 44); EXPECT_EQ(ParseFixed6Fraction("703125"), 45); EXPECT_EQ(ParseFixed6Fraction("71875"), 46); EXPECT_EQ(ParseFixed6Fraction("734375"), 47); EXPECT_EQ(ParseFixed6Fraction("75"), 48); EXPECT_EQ(ParseFixed6Fraction("765625"), 49); EXPECT_EQ(ParseFixed6Fraction("78125"), 50); EXPECT_EQ(ParseFixed6Fraction("796875"), 51); EXPECT_EQ(ParseFixed6Fraction("8125"), 52); EXPECT_EQ(ParseFixed6Fraction("828125"), 53); EXPECT_EQ(ParseFixed6Fraction("84375"), 54); EXPECT_EQ(ParseFixed6Fraction("859375"), 55); EXPECT_EQ(ParseFixed6Fraction("875"), 56); EXPECT_EQ(ParseFixed6Fraction("890625"), 57); EXPECT_EQ(ParseFixed6Fraction("90625"), 58); EXPECT_EQ(ParseFixed6Fraction("921875"), 59); EXPECT_EQ(ParseFixed6Fraction("9375"), 60); EXPECT_EQ(ParseFixed6Fraction("953125"), 61); EXPECT_EQ(ParseFixed6Fraction("96875"), 62); EXPECT_EQ(ParseFixed6Fraction("984375"), 63); EXPECT_EQ(ParseFixed6Fraction("99218749"), 63); EXPECT_EQ(ParseFixed6Fraction("9921875"), 64); } TEST(ParseInt, ParseFixed6) { ParseIntResult result = ParseFixed6(""); ASSERT_FALSE(result.has_value()) << "Empty strings are not valid fixed point values."; EXPECT_EQ(result.error(), ParseIntError::ParseError) << "ParseFixed6 should give a ParseError code when parsing an empty string."; result = ParseFixed6("abcd"); ASSERT_FALSE(result.has_value()) << "Non-numeric strings should not be parsed as a fixed-point value."; EXPECT_EQ(result.error(), ParseIntError::ParseError) << "ParseFixed6 should give a ParseError code when parsing a non-numeric string."; result = ParseFixed6("."); ASSERT_FALSE(result.has_value()) << "To match std::from_chars ParseFixed6 should fail to parse a decimal string with no digits."; EXPECT_EQ(result.error(), ParseIntError::ParseError) << "Decimal strings with no digits are reported as ParseError codes."; result = ParseFixed6("1."); ASSERT_TRUE(result.has_value()) << "A trailing decimal point is permitted for fixed point values"; EXPECT_EQ(result.value(), 1 << 6); result = ParseFixed6(".5"); ASSERT_TRUE(result.has_value()) << "A fixed point value with no integer part is accepted"; EXPECT_EQ(result.value(), 32); const std::string_view badString { "-." }; const char *endOfParse = nullptr; result = ParseFixed6(badString, &endOfParse); ASSERT_FALSE(result.has_value()) << "To match std::from_chars ParseFixed6 should fail to parse a decimal string with no digits, even if it starts with a minus sign."; EXPECT_EQ(result.error(), ParseIntError::ParseError) << "Decimal strings with no digits are reported as ParseError codes."; EXPECT_EQ(endOfParse, badString.data()) << "Failed fixed point parsing should set the end pointer to match the start of the string even though it read multiple characters"; result = ParseFixed6("-1."); ASSERT_TRUE(result.has_value()) << "negative fixed point values are handled when reading into signed types"; EXPECT_EQ(result.value(), -1 << 6); result = ParseFixed6("-1.25"); ASSERT_TRUE(result.has_value()) << "negative fixed point values are handled when reading into signed types"; EXPECT_EQ(result.value(), -((1 << 6) + 16)) << "and the fraction part is combined with the integer part respecting the sign"; result = ParseFixed6("-.25"); ASSERT_TRUE(result.has_value()) << "negative fixed point values with no integer digits are handled when reading into signed types"; EXPECT_EQ(result.value(), -16) << "and the fraction part is used respecting the sign"; result = ParseFixed6("-0.25"); ASSERT_TRUE(result.has_value()) << "negative fixed point values with an explicit -0 integer part are handled when reading into signed types"; EXPECT_EQ(result.value(), -16) << "and the fraction part is used respecting the sign"; ParseIntResult unsignedResult = ParseFixed6("-1."); ASSERT_FALSE(unsignedResult.has_value()) << "negative fixed point values are not permitted when reading into unsigned types"; EXPECT_EQ(unsignedResult.error(), ParseIntError::ParseError) << "Attempting to parse a negative value into an unsigned type is a ParseError, not an OutOfRange value"; } } // namespace devilution