94 lines
3.2 KiB
Python
94 lines
3.2 KiB
Python
from __future__ import annotations
|
|
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
from setprotocol.firmware_publish import (
|
|
FirmwarePublication,
|
|
firmware_release_entry,
|
|
firmware_release_tag,
|
|
update_firmware_manifest,
|
|
)
|
|
|
|
|
|
class FirmwarePublishTests(unittest.TestCase):
|
|
def publication(self, path: Path, **overrides) -> FirmwarePublication:
|
|
fields = {
|
|
"path": path,
|
|
"product": "F103DS18",
|
|
"version_name": "1.1.0",
|
|
"version_code": 0x00010100,
|
|
"transport": "can",
|
|
"base_address": 0x08003000,
|
|
"notes": "Verified release",
|
|
}
|
|
fields.update(overrides)
|
|
return FirmwarePublication(**fields)
|
|
|
|
def test_publication_validates_file_and_metadata(self) -> None:
|
|
with tempfile.TemporaryDirectory() as temporary:
|
|
image = Path(temporary) / "image.hex"
|
|
image.write_text(":00000001FF\n", encoding="ascii")
|
|
self.publication(image).validate()
|
|
with self.assertRaisesRegex(ValueError, "Unsupported"):
|
|
self.publication(image, transport="unknown").validate()
|
|
|
|
def test_entry_and_tag_are_deterministic(self) -> None:
|
|
publication = self.publication(Path("image.hex"))
|
|
entry = firmware_release_entry(
|
|
publication, "https://example.test/image.hex", "ab" * 32
|
|
)
|
|
self.assertEqual(
|
|
firmware_release_tag(publication), "firmware-F103DS18-v1.1.0"
|
|
)
|
|
self.assertEqual(entry["baseAddress"], "0x08003000")
|
|
|
|
def test_update_preserves_sections_and_replaces_same_release(self) -> None:
|
|
first = {
|
|
"product": "Device",
|
|
"versionCode": 7,
|
|
"versionName": "1.2.3",
|
|
"imageUrl": "https://example.test/old.bin",
|
|
"fileName": "old.bin",
|
|
"sha256": "11" * 32,
|
|
"transport": "rs485",
|
|
}
|
|
manifest = update_firmware_manifest(
|
|
{"windows": {"versionCode": 8}}, first
|
|
)
|
|
replacement = {
|
|
**first,
|
|
"imageUrl": "https://example.test/new.bin",
|
|
"fileName": "new.bin",
|
|
"sha256": "22" * 32,
|
|
}
|
|
updated = update_firmware_manifest(manifest, replacement)
|
|
self.assertEqual(updated["windows"], {"versionCode": 8})
|
|
self.assertEqual(len(updated["firmware"]["releases"]), 1)
|
|
self.assertEqual(
|
|
updated["firmware"]["releases"][0]["sha256"], "22" * 32
|
|
)
|
|
self.assertEqual(updated["firmware"]["catalogVersion"], 2)
|
|
|
|
def test_legacy_array_is_migrated_without_data_loss(self) -> None:
|
|
legacy = {
|
|
"product": "Legacy",
|
|
"versionCode": 1,
|
|
"versionName": "1.0",
|
|
"imageUrl": "https://example.test/legacy.bin",
|
|
"fileName": "legacy.bin",
|
|
"sha256": "33" * 32,
|
|
"transport": "rs485",
|
|
}
|
|
current = {**legacy, "product": "Current", "versionCode": 2}
|
|
updated = update_firmware_manifest({"firmware": [legacy]}, current)
|
|
self.assertCountEqual(
|
|
[row["product"] for row in updated["firmware"]["releases"]],
|
|
["Legacy", "Current"],
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|