Skip to content

feat(testing): serve V1 maps from the simulator - #1000

Merged
allenporter merged 2 commits into
mainfrom
codex/v1-map-simulator
Oct 31, 2026
Merged

allenporter merged 2 commits into
mainfrom
codex/v1-map-simulator

Conversation

@Lash-L

@Lash-L Lash-L commented Oct 31, 2026 •

Copy link
Copy Markdown
Collaborator

V1VacuumSimulator currently does not answer get_map_v1, so simulator tests cannot exercise full-map transport and rendering. Add a stateful synthetic map with image, path, mop flags, and robot pose, and serve it as a gzipped, AES-CBC-encrypted binary response through the existing map decoder. Correct the simulator endpoint and nonce lengths so those responses can decrypt.

The image bounds include the robot and path, and generated files carry the correct payload length, version and SHA-1 digest. Custom get_map_v1 handlers can return decompressed map bytes or emit an RPC error through the existing handler mechanism. This change is independent of the dynamic-map helpers.

Tests cover a connected device fetching a map, visible path and robot overlays, bounds at several path lengths and positions, full-file length and digest validation, and custom map handlers.

Validation:

  • pytest -q -p no:cacheprovider: 1,611 passed, 53 expected failures, 11 deselected; 99 snapshots passed.
  • pre-commit run --all-files: all hooks passed.

Copilot AI balanced review requested due to automatic review settings October 31, 2026 01:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

@codecov

codecov Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

Files with missing lines Coverage Δ
roborock/testing/v1_simulator.py 87.70% <100.00%> (+6.95%) ⬆️
tests/testing/test_v1_simulator.py 100.00% <100.00%> (ø)

... and 2 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Teach V1VacuumSimulator to answer get_map_v1 the way a device does: an
encrypted, gzipped binary frame on the map response protocol rather than
a JSON result. The simulated map carries a small image, a path that tests
grow with advance_path(), and the robot pose, and parses through the real
map decoder and renderer.

The simulator's security data was never usable for this: the endpoint did
not fit the eight byte header field and the nonce was not a valid sixteen
byte AES key. Replace both with values that decode.
@Lash-L
Lash-L force-pushed the codex/v1-map-simulator branch from 780f98c to cab1296 Compare October 31, 2026 01:14

@Lash-L Lash-L left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated code review by Gemini 4 Argon in Antigravity using the /code-review skill (.agents/skills/code-review/SKILL.md / AGENTS.md).

Summary

Clean, well-scoped addition (~200 LOC) teaching V1VacuumSimulator to serve gzipped, AES-CBC-encrypted MAP_RESPONSE frames for get_map_v1 through the real V1Channel.map_rpc_channel decoder and MapParser.

  • PR Scoping & Isolation: Keeps the simulator map synthesis independent of #1001 so both PRs can land in either order. (Once both merge, _block and _DIGEST_BLOCK_TYPE in roborock/testing/v1_simulator.py could optionally reuse MapBlock and DIGEST_BLOCK_TYPE from roborock.map.dynamic_blocks).
  • Layer 2 & 3 — Wire Framing & State Flow: Fixing SecurityData (endpoint to 8 bytes and nonce to 16 bytes) and routing get_map_v1 byte payloads through RoborockMessageProtocol.MAP_RESPONSE while preserving JSON-RPC error responses for failing custom handlers exercises the full production map pipeline end-to-end.
  • Layer 5 — Tests & Fixtures: Colocated in tests/testing/test_v1_simulator.py with @pytest.mark.parametrize covering path lengths, robot positions, drawable overlays, SHA-1 digests, and custom handler overrides.

No blocking issues found.

@Lash-L
Lash-L requested a review from allenporter October 31, 2026 01:38
@allenporter
allenporter merged commit 4c0586d into main Oct 31, 2026
10 checks passed

def _path_point(index: int) -> bytes:
"""A deterministic path point, so tests can assert on exact bytes."""
return struct.pack("<HH", 20000 + index * 10, 21000 + index * 7)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_path_point packs x as an unsigned short with 20000 + index * 10. At index 4554 that's 65540, which doesn't fit, so struct.pack raises. (y overflows too, at 6363.)

sim = V1VacuumSimulator()
sim.advance_path(5000)
sim.build_map_bytes()  # struct.error

Through the device, _handle_publish catches it and the map request comes back as an RPC error with the struct message, which is a confusing failure for someone simulating a long clean.

Current tests use 7 to 40 points, so nothing hits it today. Easy fixes: wrap the index, e.g. 20000 + (index * 10) % 40000, or reject big counts in advance_path with a clear message.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants