-
Notifications
You must be signed in to change notification settings - Fork 1
feat(python): add reset_device() to SerialMonitor #52
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+160
−0
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| reviews: | ||
| request_changes_workflow: true | ||
| pre_merge_checks: | ||
| enabled: true |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| """RED tests: SerialMonitor.reset_device() must exist and return bool. | ||
|
|
||
| These tests verify the PyO3 binding exposes reset_device() on SerialMonitor. | ||
| They will FAIL until the Rust implementation is added. | ||
| """ | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| def test_serial_monitor_has_reset_device() -> None: | ||
| """SerialMonitor must expose a reset_device method.""" | ||
| from fbuild._native import SerialMonitor | ||
|
|
||
| assert hasattr(SerialMonitor, "reset_device"), ( | ||
| "SerialMonitor is missing reset_device method. " | ||
| "Add #[pyo3] fn reset_device(&self, board: Option<String>) -> PyResult<bool> " | ||
| "to the SerialMonitor impl block in crates/fbuild-python/src/lib.rs" | ||
| ) | ||
|
|
||
|
|
||
| def test_serial_monitor_reset_device_is_callable() -> None: | ||
| """reset_device must be callable (not just an attribute).""" | ||
| from fbuild._native import SerialMonitor | ||
|
|
||
| mon = SerialMonitor(port="COM13", baud_rate=115200) | ||
| assert callable(getattr(mon, "reset_device", None)), ( | ||
| "SerialMonitor.reset_device exists but is not callable" | ||
| ) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| """Integration test: reset a real ESP32-S3 via the fbuild daemon. | ||
|
|
||
| Requires: | ||
| - fbuild daemon running | ||
| - ESP32-S3 device on COM13 | ||
| - Device flashed with AutoResearch firmware | ||
|
|
||
| Skip conditions checked at import time. | ||
| """ | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| import time | ||
|
|
||
| import pytest | ||
| import serial.tools.list_ports as list_ports | ||
|
|
||
|
|
||
| def _port_exists(port: str) -> bool: | ||
| """Check if a serial port is enumerated (without opening it). | ||
|
|
||
| Uses pyserial's port enumeration instead of opening the port, | ||
| which would conflict with a daemon holding the port open. | ||
| """ | ||
| return any(info.device == port for info in list_ports.comports()) | ||
|
|
||
|
|
||
| def _daemon_running() -> bool: | ||
| """Check if the fbuild daemon is reachable.""" | ||
| try: | ||
| import urllib.request | ||
|
|
||
| urllib.request.urlopen("http://127.0.0.1:8765/health", timeout=2) | ||
| return True | ||
| except Exception: | ||
| return False | ||
|
|
||
|
|
||
| @pytest.mark.skipif(not _port_exists("COM13"), reason="COM13 not available") | ||
| @pytest.mark.skipif(not _daemon_running(), reason="fbuild daemon not running") | ||
| def test_reset_esp32s3_and_read_output() -> None: | ||
| """After reset_device, a fresh monitor should capture device output.""" | ||
| from fbuild._native import SerialMonitor | ||
|
|
||
| # Reset first (no monitor attached — avoids preemption race) | ||
| mon = SerialMonitor(port="COM13", baud_rate=115200) | ||
| result = mon.reset_device(board="esp32s3") | ||
| assert result is True, "reset_device should return True on success" | ||
|
|
||
| # Wait for reboot | ||
| time.sleep(3.0) | ||
|
|
||
| # Now attach a fresh monitor and read output | ||
| with SerialMonitor(port="COM13", baud_rate=115200) as mon2: | ||
| lines = mon2.read_lines(timeout=5.0) | ||
| assert len(lines) > 0, ( | ||
| "Device should produce serial output after reset. " | ||
| "Got 0 lines — device may not have rebooted." | ||
| ) | ||
|
|
||
|
|
||
| @pytest.mark.skipif(not _port_exists("COM13"), reason="COM13 not available") | ||
| @pytest.mark.skipif(not _daemon_running(), reason="fbuild daemon not running") | ||
| def test_reset_device_without_enter() -> None: | ||
| """reset_device should work without calling __enter__ first.""" | ||
| from fbuild._native import SerialMonitor | ||
|
|
||
| mon = SerialMonitor(port="COM13", baud_rate=115200) | ||
| # Should NOT require __enter__ — reset goes through HTTP, not WebSocket | ||
| result = mon.reset_device(board="esp32s3") | ||
| assert isinstance(result, bool), "reset_device must return a bool" | ||
| assert result is True, "reset_device should succeed for a connected ESP32-S3" | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.