From 54d9c724f328445efaa724fc4eb152f609502422 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 20 Aug 2026 22:26:52 -0500 Subject: [PATCH] [api] Make try_advance return void; tests assert via iterator state --- esphome/core/component_iterator.h | 6 +-- .../core/test_component_iterator.cpp | 45 +++++++++++-------- 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/esphome/core/component_iterator.h b/esphome/core/component_iterator.h index 10f737a3ec..fac09e9e14 100644 --- a/esphome/core/component_iterator.h +++ b/esphome/core/component_iterator.h @@ -32,9 +32,8 @@ class ComponentIterator { void begin(bool include_internal = false); /// Run up to max_steps iteration steps; stops early when iteration /// completes or a callback refuses (that step is retried on the next - /// call). Returns the number of steps that made progress. - /// Inline so an idle (completed) iterator costs one compare, no call. - ESPHOME_ALWAYS_INLINE size_t try_advance(size_t max_steps) { + /// call). Inline so an idle (completed) iterator costs one compare, no call. + ESPHOME_ALWAYS_INLINE void try_advance(size_t max_steps) { size_t steps = 0; while (steps < max_steps && !this->completed()) { this->yield_requested_ = false; @@ -44,7 +43,6 @@ class ComponentIterator { if (this->yield_requested_) break; } - return steps; } // Remove before 2027.3.0 ESPDEPRECATED("Use try_advance() instead. Removed in 2027.3.0", "2026.8.1") diff --git a/tests/components/core/test_component_iterator.cpp b/tests/components/core/test_component_iterator.cpp index 5c4e8ab10e..c1218227c4 100644 --- a/tests/components/core/test_component_iterator.cpp +++ b/tests/components/core/test_component_iterator.cpp @@ -47,14 +47,16 @@ static constexpr size_t BIG_BUDGET = 1000; TEST(ComponentIterator, NotRunningMakesNoProgress) { RefusingIterator it; - EXPECT_EQ(it.try_advance(BIG_BUDGET), 0u); + it.try_advance(BIG_BUDGET); EXPECT_TRUE(it.completed()); + EXPECT_EQ(it.begin_calls, 0); + EXPECT_EQ(it.end_calls, 0); } TEST(ComponentIterator, CompletesInOneCallWithoutRefusals) { RefusingIterator it; it.begin(); - EXPECT_GT(it.try_advance(BIG_BUDGET), 0u); + it.try_advance(BIG_BUDGET); EXPECT_TRUE(it.completed()); EXPECT_EQ(it.begin_calls, 1); EXPECT_EQ(it.end_calls, 1); @@ -63,7 +65,9 @@ TEST(ComponentIterator, CompletesInOneCallWithoutRefusals) { TEST(ComponentIterator, StepBudgetIsHonored) { RefusingIterator it; it.begin(); - EXPECT_EQ(it.try_advance(1), 1u); + it.try_advance(1); + EXPECT_EQ(it.begin_calls, 1); + EXPECT_EQ(it.end_calls, 0); EXPECT_FALSE(it.completed()); } @@ -71,15 +75,17 @@ TEST(ComponentIterator, RefusedStepStopsBatchAndRetriesSameStep) { RefusingIterator it; it.end_refusals = 3; it.begin(); - // First call runs until the refused end step - EXPECT_GT(it.try_advance(BIG_BUDGET), 0u); + // First call runs until the refused end step, which stops the pass + it.try_advance(BIG_BUDGET); + EXPECT_EQ(it.end_calls, 1); EXPECT_FALSE(it.completed()); - // The refused step is retried, not skipped - EXPECT_EQ(it.try_advance(BIG_BUDGET), 0u); - EXPECT_EQ(it.try_advance(BIG_BUDGET), 0u); + // The refused step is retried once per call, not skipped + it.try_advance(BIG_BUDGET); + it.try_advance(BIG_BUDGET); + EXPECT_EQ(it.end_calls, 3); EXPECT_FALSE(it.completed()); // Once accepted, the iteration completes - EXPECT_GT(it.try_advance(BIG_BUDGET), 0u); + it.try_advance(BIG_BUDGET); EXPECT_TRUE(it.completed()); EXPECT_EQ(it.end_calls, 4); } @@ -88,9 +94,11 @@ TEST(ComponentIterator, RefusedBeginStopsBatchAndRetries) { RefusingIterator it; it.begin_refusals = 2; it.begin(); - EXPECT_EQ(it.try_advance(BIG_BUDGET), 0u); - EXPECT_EQ(it.try_advance(BIG_BUDGET), 0u); - EXPECT_GT(it.try_advance(BIG_BUDGET), 0u); + it.try_advance(BIG_BUDGET); + it.try_advance(BIG_BUDGET); + EXPECT_EQ(it.begin_calls, 2); + EXPECT_FALSE(it.completed()); + it.try_advance(BIG_BUDGET); EXPECT_TRUE(it.completed()); EXPECT_EQ(it.begin_calls, 3); } @@ -153,14 +161,15 @@ TEST_F(ComponentIteratorSensorTest, RefusedItemIsReofferedNotSkipped) { it.sensor_refusals = 2; it.begin(); // Runs until the first sensor refuses - EXPECT_GT(it.try_advance(BIG_BUDGET), 0u); + it.try_advance(BIG_BUDGET); EXPECT_EQ(it.sensor_calls, 1); EXPECT_FALSE(it.completed()); // The refused item is re-offered, not skipped - EXPECT_EQ(it.try_advance(BIG_BUDGET), 0u); + it.try_advance(BIG_BUDGET); + EXPECT_EQ(it.sensor_calls, 2); sensor::Sensor *refused = it.last_sensor; // Once accepted, iteration continues through the second sensor to the end - EXPECT_GT(it.try_advance(BIG_BUDGET), 0u); + it.try_advance(BIG_BUDGET); EXPECT_TRUE(it.completed()); EXPECT_NE(it.last_sensor, refused); EXPECT_EQ(it.sensor_calls, 4); @@ -171,14 +180,14 @@ TEST_F(ComponentIteratorSensorTest, YieldAfterStepEndsPassAndResumes) { it.yield_on_sensor = true; it.begin(); // The pass ends right after the first sensor despite a big budget - EXPECT_GT(it.try_advance(BIG_BUDGET), 0u); + it.try_advance(BIG_BUDGET); EXPECT_EQ(it.sensor_calls, 1); EXPECT_FALSE(it.completed()); // The next pass ends after the second sensor - EXPECT_GT(it.try_advance(BIG_BUDGET), 0u); + it.try_advance(BIG_BUDGET); EXPECT_EQ(it.sensor_calls, 2); // Remaining states then run to completion in one pass - EXPECT_GT(it.try_advance(BIG_BUDGET), 0u); + it.try_advance(BIG_BUDGET); EXPECT_TRUE(it.completed()); } #endif // USE_SENSOR