Repository navigation
feat(testing): serve V1 maps from the simulator - #1000
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests.
... and 2 files with indirect coverage changes 🚀 New features to boost your workflow:
|
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.
780f98c to
cab1296
Compare
Lash-L
left a comment
There was a problem hiding this comment.
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,
_blockand_DIGEST_BLOCK_TYPEinroborock/testing/v1_simulator.pycould optionally reuseMapBlockandDIGEST_BLOCK_TYPEfromroborock.map.dynamic_blocks). - Layer 2 & 3 — Wire Framing & State Flow: Fixing
SecurityData(endpointto 8 bytes andnonceto 16 bytes) and routingget_map_v1byte payloads throughRoborockMessageProtocol.MAP_RESPONSEwhile 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.pywith@pytest.mark.parametrizecovering path lengths, robot positions, drawable overlays, SHA-1 digests, and custom handler overrides.
No blocking issues found.
|
|
||
| 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) |
There was a problem hiding this comment.
_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.errorThrough 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.
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.