mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 22:53:59 +00:00 
			
		
		
		
	improve test
This commit is contained in:
		| @@ -44,9 +44,9 @@ void DeferStressComponent::run_multi_thread_test() { | |||||||
|         auto *component = this; |         auto *component = this; | ||||||
|  |  | ||||||
|         // Directly call defer() from this thread - no locking! |         // Directly call defer() from this thread - no locking! | ||||||
|         this->defer([component, defer_id]() { |         this->defer([component, i, j, defer_id]() { | ||||||
|           component->executed_defers_.fetch_add(1); |           component->executed_defers_.fetch_add(1); | ||||||
|           ESP_LOGV(TAG, "Executed defer %d", defer_id); |           ESP_LOGV(TAG, "Executed defer %d (thread %d, index %d)", defer_id, i, j); | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|         ESP_LOGV(TAG, "Thread %d called defer for request %d successfully", i, defer_id); |         ESP_LOGV(TAG, "Thread %d called defer for request %d successfully", i, defer_id); | ||||||
| @@ -68,19 +68,7 @@ void DeferStressComponent::run_multi_thread_test() { | |||||||
|   auto end_time = std::chrono::steady_clock::now(); |   auto end_time = std::chrono::steady_clock::now(); | ||||||
|   auto thread_time = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time).count(); |   auto thread_time = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time).count(); | ||||||
|   ESP_LOGI(TAG, "All threads finished in %lldms. Created %d defer requests", thread_time, this->total_defers_.load()); |   ESP_LOGI(TAG, "All threads finished in %lldms. Created %d defer requests", thread_time, this->total_defers_.load()); | ||||||
|  |  | ||||||
|   // Store the final values for checking |  | ||||||
|   this->expected_total_ = NUM_THREADS * DEFERS_PER_THREAD; |  | ||||||
|   this->test_complete_ = true; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| int DeferStressComponent::get_total_defers() { return this->total_defers_.load(); } |  | ||||||
|  |  | ||||||
| int DeferStressComponent::get_executed_defers() { return this->executed_defers_.load(); } |  | ||||||
|  |  | ||||||
| bool DeferStressComponent::is_test_complete() { return this->test_complete_; } |  | ||||||
|  |  | ||||||
| int DeferStressComponent::get_expected_total() { return this->expected_total_; } |  | ||||||
|  |  | ||||||
| }  // namespace defer_stress_component | }  // namespace defer_stress_component | ||||||
| }  // namespace esphome | }  // namespace esphome | ||||||
|   | |||||||
| @@ -11,17 +11,9 @@ class DeferStressComponent : public Component { | |||||||
|   void setup() override; |   void setup() override; | ||||||
|   void run_multi_thread_test(); |   void run_multi_thread_test(); | ||||||
|  |  | ||||||
|   // Getters for test status |  | ||||||
|   int get_total_defers(); |  | ||||||
|   int get_executed_defers(); |  | ||||||
|   bool is_test_complete(); |  | ||||||
|   int get_expected_total(); |  | ||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   std::atomic<int> total_defers_{0}; |   std::atomic<int> total_defers_{0}; | ||||||
|   std::atomic<int> executed_defers_{0}; |   std::atomic<int> executed_defers_{0}; | ||||||
|   bool test_complete_{false}; |  | ||||||
|   int expected_total_{0}; |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| }  // namespace defer_stress_component | }  // namespace defer_stress_component | ||||||
|   | |||||||
| @@ -32,22 +32,38 @@ async def test_defer_stress( | |||||||
|     loop = asyncio.get_event_loop() |     loop = asyncio.get_event_loop() | ||||||
|     test_complete_future: asyncio.Future[None] = loop.create_future() |     test_complete_future: asyncio.Future[None] = loop.create_future() | ||||||
|  |  | ||||||
|     # Track executed defers |     # Track executed defers and their order | ||||||
|     executed_defers = set() |     executed_defers = set() | ||||||
|  |     thread_executions = {}  # thread_id -> list of indices in execution order | ||||||
|  |     fifo_violations = [] | ||||||
|  |  | ||||||
|     def on_log_line(line: str) -> None: |     def on_log_line(line: str) -> None: | ||||||
|         # Track all executed defers |         # Track all executed defers with thread and index info | ||||||
|         match = re.search(r"Executed defer (\d+)", line) |         match = re.search(r"Executed defer (\d+) \(thread (\d+), index (\d+)\)", line) | ||||||
|         if match: |         if match: | ||||||
|             defer_id = int(match.group(1)) |             defer_id = int(match.group(1)) | ||||||
|  |             thread_id = int(match.group(2)) | ||||||
|  |             index = int(match.group(3)) | ||||||
|  |  | ||||||
|             executed_defers.add(defer_id) |             executed_defers.add(defer_id) | ||||||
|  |  | ||||||
|             # Check if we've executed all 1000 defers (0-999) |             # Track execution order per thread | ||||||
|  |             if thread_id not in thread_executions: | ||||||
|  |                 thread_executions[thread_id] = [] | ||||||
|  |  | ||||||
|  |             # Check FIFO ordering within thread | ||||||
|             if ( |             if ( | ||||||
|                 defer_id == 999 |                 thread_executions[thread_id] | ||||||
|                 and len(executed_defers) == 1000 |                 and thread_executions[thread_id][-1] >= index | ||||||
|                 and not test_complete_future.done() |  | ||||||
|             ): |             ): | ||||||
|  |                 fifo_violations.append( | ||||||
|  |                     f"Thread {thread_id}: index {index} executed after {thread_executions[thread_id][-1]}" | ||||||
|  |                 ) | ||||||
|  |  | ||||||
|  |             thread_executions[thread_id].append(index) | ||||||
|  |  | ||||||
|  |             # Check if we've executed all 1000 defers (0-999) | ||||||
|  |             if len(executed_defers) == 1000 and not test_complete_future.done(): | ||||||
|                 test_complete_future.set_result(None) |                 test_complete_future.set_result(None) | ||||||
|  |  | ||||||
|     async with ( |     async with ( | ||||||
| @@ -96,5 +112,22 @@ async def test_defer_stress( | |||||||
|         missing_ids = expected_ids - executed_defers |         missing_ids = expected_ids - executed_defers | ||||||
|         assert not missing_ids, f"Missing defer IDs: {sorted(missing_ids)}" |         assert not missing_ids, f"Missing defer IDs: {sorted(missing_ids)}" | ||||||
|  |  | ||||||
|         # If we got here without crashing, the test passed |         # Verify FIFO ordering was maintained within each thread | ||||||
|         assert True, "Test completed successfully - all 1000 defers executed in order" |         assert not fifo_violations, "FIFO ordering violations detected:\n" + "\n".join( | ||||||
|  |             fifo_violations[:10] | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |         # Verify each thread executed all its defers in order | ||||||
|  |         for thread_id, indices in thread_executions.items(): | ||||||
|  |             assert len(indices) == 100, ( | ||||||
|  |                 f"Thread {thread_id} executed {len(indices)} defers, expected 100" | ||||||
|  |             ) | ||||||
|  |             # Indices should be 0-99 in ascending order | ||||||
|  |             assert indices == list(range(100)), ( | ||||||
|  |                 f"Thread {thread_id} executed indices out of order: {indices[:10]}..." | ||||||
|  |             ) | ||||||
|  |  | ||||||
|  |         # If we got here without crashing and with proper ordering, the test passed | ||||||
|  |         assert True, ( | ||||||
|  |             "Test completed successfully - all 1000 defers executed with FIFO ordering preserved" | ||||||
|  |         ) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user