Skip to content

Commit e72bd72

Browse files
committed
chore: Add test coverage for failing to parse bytes
1 parent 6999f6f commit e72bd72

File tree

2 files changed

+70
-25
lines changed

2 files changed

+70
-25
lines changed

roborock/devices/traits/v1/home.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ async def discover_home(self) -> None:
8686
self._home_map_content = {
8787
k: self._map_content.parse_map_content(v) for k, v in cache_data.home_map_content.items()
8888
}
89-
except RoborockException as ex:
89+
except (ValueError, RoborockException) as ex:
9090
_LOGGER.warning("Failed to parse cached home map content, will re-discover: %s", ex)
9191
self._home_map_content = {}
9292
else:

tests/devices/traits/v1/test_home.py

Lines changed: 69 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from roborock.devices.traits.v1.maps import MapsTrait
1515
from roborock.devices.traits.v1.rooms import RoomsTrait
1616
from roborock.devices.traits.v1.status import StatusTrait
17-
from roborock.exceptions import RoborockDeviceBusy
17+
from roborock.exceptions import RoborockDeviceBusy, RoborockException
1818
from roborock.map.map_parser import ParsedMapData
1919
from roborock.roborock_typing import RoborockCommand
2020
from tests import mock_data
@@ -42,6 +42,22 @@
4242
],
4343
}
4444
]
45+
MULTI_MAP_LIST_SINGLE_MAP_DATA = [
46+
{
47+
"max_multi_map": 1,
48+
"max_bak_map": 0,
49+
"multi_map_count": 1,
50+
"map_info": [
51+
{
52+
"mapFlag": 0,
53+
"add_time": 1747132930,
54+
"length": 0,
55+
"name": "Only Floor",
56+
"bak_maps": [],
57+
},
58+
],
59+
}
60+
]
4561

4662
ROOM_MAPPING_DATA_MAP_0 = [[16, "2362048"], [17, "2362044"]]
4763
ROOM_MAPPING_DATA_MAP_123 = [[18, "2362041"], [19, "2362042"]]
@@ -241,6 +257,57 @@ async def test_discover_home_with_existing_cache(
241257
assert map_0_content.map_data is not None
242258

243259

260+
async def test_existing_home_cache_invalid_bytes(
261+
home_trait: HomeTrait,
262+
mock_rpc_channel: AsyncMock,
263+
mock_mqtt_rpc_channel: AsyncMock,
264+
mock_map_rpc_channel: AsyncMock,
265+
) -> None:
266+
"""Test that discovery is skipped when cache already exists."""
267+
# Pre-populate the cache.
268+
cache_data = await home_trait._cache.get()
269+
cache_data.home_map_info = {0: CombinedMapInfo(map_flag=0, name="Dummy", rooms=[])}
270+
# We override the map bytes parser to raise an exception above.
271+
cache_data.home_map_content = {0: MAP_BYTES_RESPONSE_1}
272+
await home_trait._cache.set(cache_data)
273+
274+
# Setup mocks for the discovery process
275+
mock_rpc_channel.send_command.side_effect = [
276+
ROOM_MAPPING_DATA_MAP_0, # Rooms for the single map
277+
]
278+
mock_mqtt_rpc_channel.send_command.side_effect = [
279+
MULTI_MAP_LIST_SINGLE_MAP_DATA, # Single map list
280+
]
281+
mock_map_rpc_channel.send_command.side_effect = [
282+
MAP_BYTES_RESPONSE_1, # Map bytes for the single map
283+
]
284+
285+
# Call discover_home. First attempt raises an exception then loading from the server
286+
# produes a valid result.
287+
with patch(
288+
"roborock.devices.traits.v1.map_content.MapParser.parse",
289+
side_effect=[
290+
RoborockException("Invalid map bytes"),
291+
ParsedMapData(
292+
image_content=TEST_IMAGE_CONTENT_2,
293+
map_data=MagicMock(),
294+
),
295+
],
296+
):
297+
await home_trait.discover_home()
298+
299+
# Verify cache was loaded from storage. The map was re-fetched from storage.
300+
assert home_trait.home_map_info
301+
assert home_trait.home_map_info.keys() == {0}
302+
assert home_trait.home_map_info[0].name == "Only Floor"
303+
assert home_trait.home_map_content
304+
assert home_trait.home_map_content.keys() == {0}
305+
map_0_content = home_trait.home_map_content[0]
306+
assert map_0_content is not None
307+
assert map_0_content.image_content == TEST_IMAGE_CONTENT_2
308+
assert map_0_content.map_data is not None
309+
310+
244311
async def test_discover_home_no_maps(
245312
home_trait: HomeTrait,
246313
mock_rpc_channel: AsyncMock,
@@ -311,10 +378,6 @@ async def test_refresh_no_cache_no_update(
311378
mock_mqtt_rpc_channel: AsyncMock,
312379
) -> None:
313380
"""Test that refresh doesn't update when no cache exists."""
314-
# Setup mocks for refresh
315-
# mock_mqtt_rpc_channel.send_command.side_effect = [
316-
# MULTI_MAP_LIST_DATA, # Maps refresh
317-
# ]
318381
# Perform refresh without existing cache
319382
with pytest.raises(Exception, match="Cannot refresh home data without home cache, did you call discover_home()?"):
320383
await home_trait.refresh()
@@ -383,34 +446,16 @@ async def test_single_map_no_switching(
383446
mock_map_rpc_channel: AsyncMock,
384447
) -> None:
385448
"""Test that single map discovery doesn't trigger map switching."""
386-
single_map_data = [
387-
{
388-
"max_multi_map": 1,
389-
"max_bak_map": 0,
390-
"multi_map_count": 1,
391-
"map_info": [
392-
{
393-
"mapFlag": 0,
394-
"add_time": 1747132930,
395-
"length": 0,
396-
"name": "Only Floor",
397-
"bak_maps": [],
398-
},
399-
],
400-
}
401-
]
402-
403449
mock_rpc_channel.send_command.side_effect = [
404450
ROOM_MAPPING_DATA_MAP_0, # Rooms for the single map
405451
]
406452
mock_mqtt_rpc_channel.send_command.side_effect = [
407-
single_map_data, # Single map list
453+
MULTI_MAP_LIST_SINGLE_MAP_DATA, # Single map list
408454
]
409455
mock_map_rpc_channel.send_command.side_effect = [
410456
MAP_BYTES_RESPONSE_1, # Map bytes for the single map
411457
]
412458

413-
414459
await home_trait.discover_home()
415460

416461
# Verify cache is populated

0 commit comments

Comments
 (0)