Skip to content

Commit 7919c22

Browse files
committed
test(import bin): added pytests
1 parent a05d865 commit 7919c22

5 files changed

Lines changed: 2079 additions & 1031 deletions

tests/test_backend_filesystem_vehicle_components.py

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1519,3 +1519,205 @@ def test_get_fc_fw_version_missing_components(self, mock_fs_class) -> None:
15191519

15201520
# Verify empty string is returned
15211521
assert version == ""
1522+
1523+
1524+
class TestSetFcFwVersionAndTypeInComponentsJson:
1525+
"""BDD tests for set_fc_fw_version_and_type_in_components_json."""
1526+
1527+
@pytest.fixture
1528+
def vehicle_components_with_data(self) -> VehicleComponents:
1529+
"""Fixture providing a VehicleComponents instance with typical component data."""
1530+
vc = VehicleComponents()
1531+
vc.vehicle_components_fs.data = {
1532+
"Components": {
1533+
"Flight Controller": {
1534+
"Firmware": {"Type": "ArduCopter", "Version": "4.6.0"},
1535+
"Product": {"Manufacturer": "Holybro", "Model": "Pixhawk 6C"},
1536+
}
1537+
}
1538+
}
1539+
return vc
1540+
1541+
def test_firmware_version_is_written_into_component_data(self, vehicle_components_with_data: VehicleComponents) -> None:
1542+
"""
1543+
The firmware version is correctly updated in the in-memory component data.
1544+
1545+
GIVEN: Components data that has a placeholder firmware version "4.6.0"
1546+
WHEN: set_fc_fw_version_and_type_in_components_json is called with "4.6.3"
1547+
THEN: The Firmware Version field in the component data is updated to "4.6.3"
1548+
"""
1549+
vc = vehicle_components_with_data
1550+
with patch.object(vc, "save_vehicle_components_json_data", return_value=(False, "")):
1551+
vc.set_fc_fw_version_and_type_in_components_json("4.6.3", "ArduCopter", "/vehicles/test")
1552+
1553+
assert vc.vehicle_components_fs.data is not None
1554+
version = vc.vehicle_components_fs.data["Components"]["Flight Controller"]["Firmware"]["Version"]
1555+
assert version == "4.6.3"
1556+
1557+
def test_firmware_type_is_written_into_component_data(self, vehicle_components_with_data: VehicleComponents) -> None:
1558+
"""
1559+
The firmware type is correctly updated in the in-memory component data.
1560+
1561+
GIVEN: Components data that has firmware Type "ArduCopter"
1562+
WHEN: set_fc_fw_version_and_type_in_components_json is called with "Rover"
1563+
THEN: The Firmware Type field is updated to "Rover"
1564+
"""
1565+
vc = vehicle_components_with_data
1566+
with patch.object(vc, "save_vehicle_components_json_data", return_value=(False, "")):
1567+
vc.set_fc_fw_version_and_type_in_components_json("4.5.1", "Rover", "/vehicles/rover_project")
1568+
1569+
assert vc.vehicle_components_fs.data is not None
1570+
fw_type = vc.vehicle_components_fs.data["Components"]["Flight Controller"]["Firmware"]["Type"]
1571+
assert fw_type == "Rover"
1572+
1573+
def test_save_is_called_with_updated_data_and_correct_directory(
1574+
self, vehicle_components_with_data: VehicleComponents
1575+
) -> None:
1576+
"""
1577+
save_vehicle_components_json_data is called with the updated data and the given vehicle_dir.
1578+
1579+
GIVEN: Component data in memory and a known vehicle directory path
1580+
WHEN: set_fc_fw_version_and_type_in_components_json is called
1581+
THEN: save_vehicle_components_json_data receives the full data dict and the correct path
1582+
"""
1583+
vc = vehicle_components_with_data
1584+
with patch.object(vc, "save_vehicle_components_json_data", return_value=(False, "")) as mock_save:
1585+
vc.set_fc_fw_version_and_type_in_components_json("4.6.3", "ArduCopter", "/vehicles/my_project")
1586+
1587+
mock_save.assert_called_once()
1588+
saved_data, saved_dir = mock_save.call_args.args
1589+
assert saved_dir == "/vehicles/my_project"
1590+
assert saved_data["Components"]["Flight Controller"]["Firmware"]["Version"] == "4.6.3"
1591+
assert saved_data["Components"]["Flight Controller"]["Firmware"]["Type"] == "ArduCopter"
1592+
1593+
def test_other_component_fields_are_not_disturbed(self, vehicle_components_with_data: VehicleComponents) -> None:
1594+
"""
1595+
Non-firmware component fields remain intact after the firmware update.
1596+
1597+
GIVEN: Components data that includes manufacturer and model information
1598+
WHEN: set_fc_fw_version_and_type_in_components_json is called
1599+
THEN: Product Manufacturer and Model are unchanged
1600+
"""
1601+
vc = vehicle_components_with_data
1602+
with patch.object(vc, "save_vehicle_components_json_data", return_value=(False, "")):
1603+
vc.set_fc_fw_version_and_type_in_components_json("4.6.3", "ArduCopter", "/vehicles/test")
1604+
1605+
assert vc.vehicle_components_fs.data is not None
1606+
product = vc.vehicle_components_fs.data["Components"]["Flight Controller"]["Product"]
1607+
assert product["Manufacturer"] == "Holybro"
1608+
assert product["Model"] == "Pixhawk 6C"
1609+
1610+
def test_creates_firmware_section_when_absent(self) -> None:
1611+
"""
1612+
The Firmware sub-dict is created if the Flight Controller component lacks it.
1613+
1614+
GIVEN: Components data where "Flight Controller" has no "Firmware" key at all
1615+
WHEN: set_fc_fw_version_and_type_in_components_json is called
1616+
THEN: A "Firmware" section is created and populated with Version and Type
1617+
"""
1618+
vc = VehicleComponents()
1619+
vc.vehicle_components_fs.data = {"Components": {"Flight Controller": {"Product": {"Model": "CubeOrange"}}}}
1620+
1621+
with patch.object(vc, "save_vehicle_components_json_data", return_value=(False, "")):
1622+
vc.set_fc_fw_version_and_type_in_components_json("4.6.3", "ArduCopter", "/vehicles/test")
1623+
1624+
firmware = vc.vehicle_components_fs.data["Components"]["Flight Controller"]["Firmware"]
1625+
assert firmware["Version"] == "4.6.3"
1626+
assert firmware["Type"] == "ArduCopter"
1627+
1628+
def test_creates_flight_controller_section_when_absent(self) -> None:
1629+
"""
1630+
The Flight Controller section is created if the Components dict lacks it entirely.
1631+
1632+
GIVEN: Components data that has no "Flight Controller" key
1633+
WHEN: set_fc_fw_version_and_type_in_components_json is called
1634+
THEN: "Flight Controller" → "Firmware" is created with the correct values
1635+
"""
1636+
vc = VehicleComponents()
1637+
vc.vehicle_components_fs.data = {"Components": {}}
1638+
1639+
with patch.object(vc, "save_vehicle_components_json_data", return_value=(False, "")):
1640+
vc.set_fc_fw_version_and_type_in_components_json("4.6.3", "ArduCopter", "/vehicles/test")
1641+
1642+
firmware = vc.vehicle_components_fs.data["Components"]["Flight Controller"]["Firmware"]
1643+
assert firmware["Version"] == "4.6.3"
1644+
assert firmware["Type"] == "ArduCopter"
1645+
1646+
def test_does_nothing_when_data_is_none(self) -> None:
1647+
"""
1648+
No save is attempted when the component data is None.
1649+
1650+
GIVEN: vehicle_components_fs.data is None (vehicle_components.json was never loaded)
1651+
WHEN: set_fc_fw_version_and_type_in_components_json is called
1652+
THEN: save_vehicle_components_json_data is NOT called and no exception is raised
1653+
"""
1654+
vc = VehicleComponents()
1655+
vc.vehicle_components_fs.data = None
1656+
1657+
with patch.object(vc, "save_vehicle_components_json_data") as mock_save:
1658+
vc.set_fc_fw_version_and_type_in_components_json("4.6.3", "ArduCopter", "/vehicles/test")
1659+
1660+
mock_save.assert_not_called()
1661+
1662+
def test_does_nothing_when_data_has_no_components_key(self) -> None:
1663+
"""
1664+
No save is attempted when the loaded data lacks the "Components" top-level key.
1665+
1666+
GIVEN: vehicle_components_fs.data is a dict without a "Components" key
1667+
WHEN: set_fc_fw_version_and_type_in_components_json is called
1668+
THEN: save_vehicle_components_json_data is NOT called
1669+
"""
1670+
vc = VehicleComponents()
1671+
vc.vehicle_components_fs.data = {"SomethingElse": {}}
1672+
1673+
with patch.object(vc, "save_vehicle_components_json_data") as mock_save:
1674+
vc.set_fc_fw_version_and_type_in_components_json("4.6.3", "ArduCopter", "/vehicles/test")
1675+
1676+
mock_save.assert_not_called()
1677+
1678+
def test_version_is_readable_back_via_get_fc_fw_version(self, vehicle_components_with_data: VehicleComponents) -> None:
1679+
"""
1680+
After setting, get_fc_fw_version_from_vehicle_components_json returns the new version.
1681+
1682+
GIVEN: Components data with an old firmware version
1683+
WHEN: set_fc_fw_version_and_type_in_components_json writes "4.6.3"
1684+
THEN: get_fc_fw_version_from_vehicle_components_json returns "4.6.3"
1685+
"""
1686+
vc = vehicle_components_with_data
1687+
with patch.object(vc, "save_vehicle_components_json_data", return_value=(False, "")):
1688+
vc.set_fc_fw_version_and_type_in_components_json("4.6.3", "ArduCopter", "/vehicles/test")
1689+
1690+
assert vc.get_fc_fw_version_from_vehicle_components_json() == "4.6.3"
1691+
1692+
def test_warning_is_logged_when_save_fails(self, vehicle_components_with_data: VehicleComponents) -> None:
1693+
"""
1694+
A warning is logged and execution continues when the save operation reports an error.
1695+
1696+
GIVEN: Component data is valid but save_vehicle_components_json_data returns an error
1697+
WHEN: set_fc_fw_version_and_type_in_components_json is called
1698+
THEN: A warning is logged containing the error message and no exception is raised
1699+
"""
1700+
vc = vehicle_components_with_data
1701+
with (
1702+
patch.object(vc, "save_vehicle_components_json_data", return_value=(True, "disk write error")),
1703+
patch("ardupilot_methodic_configurator.backend_filesystem_vehicle_components.logging_warning") as mock_warn,
1704+
):
1705+
vc.set_fc_fw_version_and_type_in_components_json("4.6.3", "ArduCopter", "/vehicles/test")
1706+
1707+
mock_warn.assert_called_once()
1708+
args = mock_warn.call_args.args
1709+
assert "disk write error" in args[1]
1710+
1711+
def test_type_is_readable_back_via_get_fc_fw_type(self, vehicle_components_with_data: VehicleComponents) -> None:
1712+
"""
1713+
After setting, get_fc_fw_type_from_vehicle_components_json returns the new type.
1714+
1715+
GIVEN: Components data with ArduCopter as the firmware type
1716+
WHEN: set_fc_fw_version_and_type_in_components_json writes "ArduPlane"
1717+
THEN: get_fc_fw_type_from_vehicle_components_json returns "ArduPlane"
1718+
"""
1719+
vc = vehicle_components_with_data
1720+
with patch.object(vc, "save_vehicle_components_json_data", return_value=(False, "")):
1721+
vc.set_fc_fw_version_and_type_in_components_json("4.5.1", "ArduPlane", "/vehicles/test")
1722+
1723+
assert vc.get_fc_fw_type_from_vehicle_components_json() == "ArduPlane"

tests/test_data_model_vehicle_components_base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1092,7 +1092,7 @@ def test_system_accepts_none_as_template_value(self, empty_model) -> None:
10921092

10931093
def test_update_json_structure_adds_arm_and_min_voltages_to_legacy_data(self, basic_model) -> None:
10941094
"""
1095-
Legacy components.json without arm/min voltages gets defaults populated.
1095+
Legacy vehicle_components.json without arm/min voltages gets defaults populated.
10961096
10971097
GIVEN: A model whose battery Specifications has Volt per cell max/low/crit but NOT arm or min
10981098
WHEN: update_json_structure() is called

0 commit comments

Comments
 (0)