#include #include #include "esphome/core/helpers.h" namespace esphome { TEST(HelpersTest, Ilog10PowersOfTen) { EXPECT_EQ(ilog10(1.0f), 0); EXPECT_EQ(ilog10(10.0f), 1); EXPECT_EQ(ilog10(100.0f), 2); EXPECT_EQ(ilog10(1000.0f), 3); EXPECT_EQ(ilog10(10000.0f), 4); EXPECT_EQ(ilog10(100000.0f), 5); EXPECT_EQ(ilog10(0.1f), -1); EXPECT_EQ(ilog10(0.001f), -3); } TEST(HelpersTest, Ilog10General) { EXPECT_EQ(ilog10(5.0f), 0); EXPECT_EQ(ilog10(9.99f), 0); EXPECT_EQ(ilog10(50.0f), 1); EXPECT_EQ(ilog10(99.0f), 1); EXPECT_EQ(ilog10(999.0f), 2); EXPECT_EQ(ilog10(0.5f), -1); EXPECT_EQ(ilog10(0.0072f), -3); EXPECT_EQ(ilog10(120000.0f), 5); EXPECT_EQ(ilog10(123456.789f), 5); } TEST(HelpersTest, Ilog10Negative) { EXPECT_EQ(ilog10(-1.0f), 0); EXPECT_EQ(ilog10(-10.0f), 1); EXPECT_EQ(ilog10(-0.1f), -1); EXPECT_EQ(ilog10(-123.456f), 2); } // Verify that ilog10 + pow10_int produces the same rounding result as log10/pow. // ilog10 may differ from floor(log10f()) for values not exactly representable in float // (e.g. 0.01f is 0.00999...), but the full round-trip must match. TEST(HelpersTest, Ilog10RoundTripMatchesLog10) { float values[] = {0.0072f, 0.05f, 0.1f, 0.5f, 1.0f, 3.14f, 9.99f, 10.0f, 42.0f, 100.0f, 1234.5f, 9999.0f, 10000.0f, 99999.0f, 120000.0f, 999999.0f, -1.0f, -0.1f, -123.456f, -10000.0f}; for (uint8_t digits = 1; digits <= 6; digits++) { for (float v : values) { // New implementation using ilog10 + pow10_int float factor_new = pow10_int(digits - 1 - ilog10(v)); float result_new = roundf(v * factor_new) / factor_new; // Reference using log10/pow double factor_ref = pow(10.0, digits - std::ceil(std::log10(std::fabs(v)))); float result_ref = static_cast(round(v * factor_ref) / factor_ref); EXPECT_FLOAT_EQ(result_new, result_ref) << "mismatch for value=" << v << " digits=" << (int) digits; } } } TEST(StaticVectorTest, ConvertingConstructorFromSmaller) { StaticVector small{0x03, 0x00, 0x10, 0x00, 0x01}; StaticVector big = small; ASSERT_EQ(big.size(), small.size()); for (size_t i = 0; i < small.size(); i++) { EXPECT_EQ(big[i], small[i]) << "mismatch at index " << i; } } TEST(StaticVectorTest, ConvertingConstructorPartiallyFilledAndEmpty) { StaticVector partial{0xAA, 0xBB}; StaticVector from_partial = partial; ASSERT_EQ(from_partial.size(), 2u); EXPECT_EQ(from_partial[0], 0xAA); EXPECT_EQ(from_partial[1], 0xBB); StaticVector empty; StaticVector from_empty = empty; EXPECT_TRUE(from_empty.empty()); } TEST(StaticVectorTest, ConvertingConstructorSameSize) { StaticVector src{1, 2, 3}; StaticVector dst = src; ASSERT_EQ(dst.size(), 3u); EXPECT_EQ(dst[2], 3); } TEST(StringContainsIgnoreCaseTest, NullPointerAlwaysFalse) { const char *haystack = nullptr; const char *needle = nullptr; EXPECT_FALSE(str_contains_ignore_case(haystack, needle)); EXPECT_FALSE(str_contains_ignore_case("Hello World", needle)); EXPECT_FALSE(str_contains_ignore_case(haystack, "anything")); } TEST(StringContainsIgnoreCaseTest, EmptySearchMatches) { const char *haystack = "Hello World"; EXPECT_TRUE(str_contains_ignore_case_fallback(haystack, "")); } TEST(StringContainsIgnoreCaseTest, MiscCaseMatches) { const char *haystack = "Hello World"; EXPECT_TRUE(str_contains_ignore_case_fallback(haystack, "Hello")); EXPECT_TRUE(str_contains_ignore_case_fallback(haystack, "hello")); EXPECT_TRUE(str_contains_ignore_case_fallback(haystack, "HELLO")); EXPECT_TRUE(str_contains_ignore_case_fallback(haystack, "hELLO")); } TEST(StringContainsIgnoreCaseTest, MiscNotMatching) { const char *haystack = "Hello World"; // Expected to match EXPECT_TRUE(str_contains_ignore_case_fallback(haystack, "Hell")); // Expected not to match EXPECT_FALSE(str_contains_ignore_case_fallback(haystack, "Heaven")); EXPECT_FALSE(str_contains_ignore_case_fallback(haystack, "Hello!")); EXPECT_FALSE(str_contains_ignore_case_fallback(haystack, "world!")); } TEST(StringContainsIgnoreCaseTest, FallbackMatchesLibc) { const char *haystack = "Hello World"; for (const char *needle : {"", "Hello", "hELLO", "Hell", "world", "Heaven", "Hello!", "d"}) { EXPECT_EQ(str_contains_ignore_case_fallback(haystack, needle), str_contains_ignore_case(haystack, needle)) << "needle: " << needle; } EXPECT_EQ(str_contains_ignore_case_fallback("", ""), str_contains_ignore_case("", "")); EXPECT_EQ(str_contains_ignore_case_fallback("ab", "abc"), str_contains_ignore_case("ab", "abc")); } } // namespace esphome