test: cover product_name string field write path in FIT patcher
Addresses review finding: no test previously exercised file_id field 8 or device_info field 27 (product_name), the only string-typed fields this task patches, leaving _write_field_value's string branch (buffer sizing, null-terminator handling) unregression-tested.
This commit is contained in:
@@ -43,6 +43,26 @@ def _build_no_device_index_fixture() -> bytes:
|
||||
return make_fit(records)
|
||||
|
||||
|
||||
def _build_product_name_fixture() -> bytes:
|
||||
"""file_id field 8 and device_info field 27 are both product_name (string) fields —
|
||||
the only string field type this task patches. No sensor record here, so the single
|
||||
device_info record present is unambiguously the creator."""
|
||||
# file_id: manufacturer(1/u16), product(2/u16), product_name(8/string, size 20)
|
||||
file_def = definition(0, FILE_ID_MESG_NUM, [(1, 2, 0x84), (2, 2, 0x84), (8, 20, 0x07)])
|
||||
original_file_name = b"MyWhoosh\x00".ljust(20, b"\x00")
|
||||
file_data = data(0, struct.pack("<HH", 255, 999) + original_file_name)
|
||||
|
||||
# device_info: device_index(0/u8), manufacturer(2/u16), product(4/u16), product_name(27/string, size 20)
|
||||
device_def = definition(
|
||||
1, DEVICE_INFO_MESG_NUM, [(0, 1, 0x02), (2, 2, 0x84), (4, 2, 0x84), (27, 20, 0x07)]
|
||||
)
|
||||
original_device_name = b"MyWhoosh App\x00".ljust(20, b"\x00")
|
||||
creator = data(1, struct.pack("<BHH", 0, 255, 999) + original_device_name)
|
||||
|
||||
records = file_def + file_data + device_def + creator
|
||||
return make_fit(records)
|
||||
|
||||
|
||||
def _read_device_info_records(path: Path) -> list[dict[int, int]]:
|
||||
"""Parse raw bytes and return one dict of {field_num: value} per device_info record,
|
||||
in file order, so creator and sensor records can be distinguished positionally."""
|
||||
@@ -124,6 +144,23 @@ def test_convert_fit_device_leaves_device_info_without_device_index_untouched(
|
||||
assert values[4] == 1234
|
||||
|
||||
|
||||
def test_convert_fit_device_patches_product_name_string_fields(tmp_path: Path) -> None:
|
||||
"""file_id field 8 and device_info field 27 (creator) are both string fields, written via
|
||||
_write_field_value's string branch (buffer sizing + null-terminator handling). Neither is
|
||||
exercised by the numeric-only base fixture used elsewhere in this module."""
|
||||
source = tmp_path / "source.fit"
|
||||
source.write_bytes(_build_product_name_fixture())
|
||||
output = tmp_path / "output.fit"
|
||||
|
||||
convert_fit_device(source, output)
|
||||
|
||||
values = read_device_field_values(output)
|
||||
values_by_key = {(v.global_message_num, v.field_num): v.value for v in values}
|
||||
|
||||
assert values_by_key[(FILE_ID_MESG_NUM, 8)] == "Edge 1030 Plus"
|
||||
assert values_by_key[(DEVICE_INFO_MESG_NUM, 27)] == "Edge 1030 Plus"
|
||||
|
||||
|
||||
def test_convert_fit_device_defaults_to_edge_1030_plus() -> None:
|
||||
device = GarminDevice()
|
||||
assert device.manufacturer_id == 1
|
||||
|
||||
Reference in New Issue
Block a user