Skip to content

Commit 0d43904

Browse files
committed
test(q7): simplify map parser follow-up fixtures
1 parent f9efa68 commit 0d43904

File tree

2 files changed

+38
-94
lines changed

2 files changed

+38
-94
lines changed

roborock/map/b01_map_parser.py

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929

3030
from .map_parser import ParsedMapData
3131

32-
_B64_CHARS = set(b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=")
3332
_MAP_FILE_FORMAT = "PNG"
3433

3534

@@ -91,9 +90,6 @@ def _derive_map_key(serial: str, model: str) -> bytes:
9190

9291
def _decode_base64_payload(raw_payload: bytes) -> bytes:
9392
blob = raw_payload.strip()
94-
if len(blob) < 32 or any(b not in _B64_CHARS for b in blob):
95-
raise RoborockException("Failed to decode B01 map payload")
96-
9793
padded = blob + b"=" * (-len(blob) % 4)
9894
try:
9995
return base64.b64decode(padded, validate=True)
@@ -125,13 +121,6 @@ def _parse_proto(blob: bytes, message: Message, *, context: str) -> None:
125121
raise RoborockException(f"Failed to parse {context}") from err
126122

127123

128-
def _decode_map_data_bytes(value: bytes) -> bytes:
129-
try:
130-
return zlib.decompress(value)
131-
except zlib.error:
132-
return value
133-
134-
135124
def _parse_scmap_payload(payload: bytes) -> RobotMap:
136125
"""Parse inflated SCMap bytes into a generated protobuf message."""
137126
parsed = RobotMap()
@@ -148,7 +137,7 @@ def _extract_grid(parsed: RobotMap) -> tuple[int, int, bytes]:
148137
if not size_x or not size_y or not parsed.mapData.HasField("mapData"):
149138
raise RoborockException("Failed to parse B01 map header/grid")
150139

151-
map_data = _decode_map_data_bytes(parsed.mapData.mapData)
140+
map_data = parsed.mapData.mapData
152141
expected_len = size_x * size_y
153142
if len(map_data) < expected_len:
154143
raise RoborockException("B01 map data shorter than expected dimensions")

tests/map/test_b01_map_parser.py

Lines changed: 37 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import gzip
33
import hashlib
44
import io
5-
import struct
65
import zlib
76
from pathlib import Path
87

@@ -13,6 +12,7 @@
1312

1413
from roborock.exceptions import RoborockException
1514
from roborock.map.b01_map_parser import B01MapParser, _parse_scmap_payload
15+
from roborock.map.proto.b01_scmap_pb2 import RobotMap # type: ignore[attr-defined]
1616

1717
FIXTURE = Path(__file__).resolve().parent / "testdata" / "raw-mqtt-map301.bin.inflated.bin.gz"
1818

@@ -26,30 +26,6 @@ def _derive_map_key(serial: str, model: str) -> bytes:
2626
return md5[8:24].encode()
2727

2828

29-
def _encode_varint(value: int) -> bytes:
30-
encoded = bytearray()
31-
while True:
32-
to_write = value & 0x7F
33-
value >>= 7
34-
if value:
35-
encoded.append(to_write | 0x80)
36-
else:
37-
encoded.append(to_write)
38-
return bytes(encoded)
39-
40-
41-
def _field_varint(field_no: int, value: int) -> bytes:
42-
return _encode_varint((field_no << 3) | 0) + _encode_varint(value)
43-
44-
45-
def _field_len(field_no: int, value: bytes) -> bytes:
46-
return _encode_varint((field_no << 3) | 2) + _encode_varint(len(value)) + value
47-
48-
49-
def _field_float32(field_no: int, value: float) -> bytes:
50-
return _encode_varint((field_no << 3) | 5) + struct.pack("<f", value)
51-
52-
5329
def test_b01_map_parser_decodes_and_renders_fixture() -> None:
5430
serial = "testsn012345"
5531
model = "roborock.vacuum.sc05"
@@ -87,62 +63,41 @@ def test_b01_map_parser_decodes_and_renders_fixture() -> None:
8763

8864

8965
def test_b01_scmap_parser_maps_observed_schema_fields() -> None:
90-
room_name_post = _field_float32(1, 11.25) + _field_float32(2, 22.5)
91-
room_one = b"".join(
92-
[
93-
_field_varint(1, 42),
94-
_field_len(2, b"Kitchen"),
95-
_field_varint(5, 1),
96-
_field_len(8, room_name_post),
97-
_field_varint(10, 7),
98-
_field_varint(12, 9),
99-
]
100-
)
101-
room_two = b"".join([_field_varint(1, 99), _field_varint(5, 0)])
102-
103-
boundary_info = b"".join(
104-
[
105-
_field_len(1, b"md5"),
106-
_field_varint(2, 10),
107-
_field_varint(3, 20),
108-
_field_varint(4, 30),
109-
_field_varint(5, 40),
110-
]
111-
)
112-
map_ext_info = b"".join(
113-
[
114-
_field_varint(1, 100),
115-
_field_varint(2, 200),
116-
_field_varint(3, 1),
117-
_field_varint(8, 3),
118-
_field_len(7, boundary_info),
119-
]
120-
)
121-
map_head = b"".join(
122-
[
123-
_field_varint(1, 7),
124-
_field_varint(2, 2),
125-
_field_varint(3, 2),
126-
_field_float32(4, 1.5),
127-
_field_float32(5, 2.5),
128-
_field_float32(6, 3.5),
129-
_field_float32(7, 4.5),
130-
_field_float32(8, 0.05),
131-
]
132-
)
133-
map_data = _field_len(1, zlib.compress(bytes([0, 127, 128, 128])))
134-
payload = b"".join(
135-
[
136-
_field_varint(1, 1),
137-
_field_len(2, map_ext_info),
138-
_field_len(3, map_head),
139-
_field_len(4, map_data),
140-
_field_len(12, room_one),
141-
_field_len(12, room_two),
142-
]
143-
)
144-
145-
parsed = _parse_scmap_payload(payload)
66+
payload = RobotMap()
67+
payload.mapType = 1
68+
payload.mapExtInfo.taskBeginDate = 100
69+
payload.mapExtInfo.mapUploadDate = 200
70+
payload.mapExtInfo.mapValid = 1
71+
payload.mapExtInfo.mapVersion = 3
72+
payload.mapExtInfo.boudaryInfo.mapMd5 = "md5"
73+
payload.mapExtInfo.boudaryInfo.vMinX = 10
74+
payload.mapExtInfo.boudaryInfo.vMaxX = 20
75+
payload.mapExtInfo.boudaryInfo.vMinY = 30
76+
payload.mapExtInfo.boudaryInfo.vMaxY = 40
77+
payload.mapHead.mapHeadId = 7
78+
payload.mapHead.sizeX = 2
79+
payload.mapHead.sizeY = 2
80+
payload.mapHead.minX = 1.5
81+
payload.mapHead.minY = 2.5
82+
payload.mapHead.maxX = 3.5
83+
payload.mapHead.maxY = 4.5
84+
payload.mapHead.resolution = 0.05
85+
payload.mapData.mapData = bytes([0, 127, 128, 128])
86+
87+
room_one = payload.roomDataInfo.add()
88+
room_one.roomId = 42
89+
room_one.roomName = "Kitchen"
90+
room_one.cleanState = 1
91+
room_one.roomNamePost.x = 11.25
92+
room_one.roomNamePost.y = 22.5
93+
room_one.colorId = 7
94+
room_one.global_seq = 9
95+
96+
room_two = payload.roomDataInfo.add()
97+
room_two.roomId = 99
98+
room_two.cleanState = 0
99+
100+
parsed = _parse_scmap_payload(payload.SerializeToString())
146101

147102
assert parsed.mapType == 1
148103
assert parsed.HasField("mapExtInfo")
@@ -157,7 +112,7 @@ def test_b01_scmap_parser_maps_observed_schema_fields() -> None:
157112
assert parsed.mapHead.resolution == pytest.approx(0.05)
158113
assert parsed.HasField("mapData")
159114
assert parsed.mapData.HasField("mapData")
160-
assert zlib.decompress(parsed.mapData.mapData) == bytes([0, 127, 128, 128])
115+
assert parsed.mapData.mapData == bytes([0, 127, 128, 128])
161116
assert parsed.roomDataInfo[0].roomId == 42
162117
assert parsed.roomDataInfo[0].roomName == "Kitchen"
163118
assert parsed.roomDataInfo[0].HasField("roomNamePost")

0 commit comments

Comments
 (0)