mirror of
https://github.com/esphome/esphome.git
synced 2026-10-15 18:52:51 +00:00
78 lines
2.5 KiB
C++
78 lines
2.5 KiB
C++
#include <gtest/gtest.h>
|
|
|
|
#include <cstdint>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <string>
|
|
|
|
#include "esphome/core/helpers.h"
|
|
|
|
namespace esphome::core::testing {
|
|
|
|
static uint32_t bits(float value) {
|
|
uint32_t out;
|
|
memcpy(&out, &value, sizeof(out));
|
|
return out;
|
|
}
|
|
|
|
// strtof is the reference: every accepted input must give the same bits.
|
|
static void expect_matches_strtof(const char *str) {
|
|
char *end = nullptr;
|
|
const float expected = ::strtof(str, &end);
|
|
const auto parsed = parse_number<float>(str);
|
|
if (!parsed.has_value()) {
|
|
ADD_FAILURE() << str << " was rejected";
|
|
return;
|
|
}
|
|
const float actual = parsed.value();
|
|
EXPECT_EQ(bits(actual), bits(expected)) << str << " parsed " << actual << " expected " << expected;
|
|
}
|
|
|
|
TEST(ParseFloat, PlainDecimalsMatchStrtof) {
|
|
for (const char *str :
|
|
{"0", "-0", "+0", "1", "-1", "100.50", "99.75", "0.1", "0.3",
|
|
"2.675", "9999999", "0.9999999", "1234.567", "-1234.567", "0.000001", "0.000000001", "12.", ".5",
|
|
"-.5", "007", "00.50", "123.4567", "0.009999999", "0.001234567", "-0.009999999"}) {
|
|
expect_matches_strtof(str);
|
|
}
|
|
}
|
|
|
|
TEST(ParseFloat, SweepOfTwoDecimalValuesMatchesStrtof) {
|
|
char buf[16];
|
|
for (int i = -20000; i <= 20000; i++) {
|
|
snprintf(buf, sizeof(buf), "%s%d.%02d", i < 0 ? "-" : "", std::abs(i) / 100, std::abs(i) % 100);
|
|
expect_matches_strtof(buf);
|
|
}
|
|
}
|
|
|
|
// A fraction longer than the fast path accepts must fall back, however long it is.
|
|
TEST(ParseFloat, LongFractionsMatchStrtof) {
|
|
std::string str = "0.";
|
|
str.append(300, '0');
|
|
str += "25";
|
|
expect_matches_strtof(str.c_str());
|
|
expect_matches_strtof(("-" + str).c_str());
|
|
str = "1.";
|
|
str.append(300, '0');
|
|
expect_matches_strtof(str.c_str());
|
|
}
|
|
|
|
TEST(ParseFloat, LibcPathInputsMatchStrtof) {
|
|
for (const char *str : {"1e3", "-2.5E-2", "0x10", "nan", " 12", "123456789", "16777215", "1.0000000", "0.0000000001",
|
|
"0.00000000001", "1.23456789", "3.4028235e38"}) {
|
|
expect_matches_strtof(str);
|
|
}
|
|
}
|
|
|
|
// Positive overflow and a positive literal infinity both come back as HUGE_VALF from strtof, and the parser
|
|
// rejects both; the negative forms pass through, as they did before the fast path.
|
|
TEST(ParseFloat, RejectsInvalidInput) {
|
|
for (const char *str :
|
|
{"", "-", "+", ".", "abc", "12abc", "1.2.3", "1,5", "12 ", "--1", "1e", "1e400", "inf", "infinity"}) {
|
|
EXPECT_FALSE(parse_number<float>(str).has_value()) << str;
|
|
}
|
|
}
|
|
|
|
} // namespace esphome::core::testing
|