fix(update): Lampe bekommt genau die geprüften Bytes
Die Registry für Einmal-URLs speicherte bisher nur einen Pfad; View und verify() lasen die Datei getrennt und zu unterschiedlichen Zeitpunkten erneut ein. Wurde die Datei zwischen Prüfung und Abruf ersetzt (z. B. gleicher Dateiname in build/ und build-nocreds/), erreichte ein nie geprüftes Image die Lampe und hebelte damit die WLAN-Sicherung aus. Jetzt werden die Bytes einmal im Install-Pfad gelesen, Gerätetyp/Version und WLAN-SSID auf genau diesen Bytes geprüft (FirmwareCatalog.verify_and_read, firmware.contains_ssid) und exakt diese Bytes in der Registry hinterlegt; die View serviert nur noch das, was tatsächlich geprüft wurde. Außerdem: Bewertungen (Katalog-Rescan-Signal) werden nicht mehr angestoßen, während ein Update läuft - das würde eine gerade flashende Lampe zusätzlich anfragen und Angebot/Issue unter dem laufenden Update verändern; nach jedem Update wird stattdessen genau einmal neu bewertet. Kommentar zum Install-Lock korrigiert (der eigentliche Lücke liegt vor dem Setzen der Flags, nicht in HAs eigener "bereits läuft"-Prüfung). Testlücke geschlossen: die View liefert jetzt nachweislich nur die zu ihrem Schlüssel gehörenden Bytes. Timeout in einem WLAN-Regressionstest verkürzt, damit er bei einem Rückfall nicht 12 Minuten hängt.
This commit is contained in:
+13
-19
@@ -18,44 +18,38 @@ from tests_unit.images import build_image
|
||||
|
||||
def test_registry_keys_are_unique_and_43_characters() -> None:
|
||||
registry = OtaRegistry()
|
||||
keys = {registry.create(Path("/tmp/a.img")) for _ in range(50)}
|
||||
keys = {registry.create(b"payload") for _ in range(50)}
|
||||
assert len(keys) == 50
|
||||
assert all(len(key) == 43 for key in keys)
|
||||
assert len(registry) == 50
|
||||
|
||||
|
||||
async def test_view_serves_only_registered_keys(
|
||||
async def test_view_serves_only_its_own_registered_bytes(
|
||||
hass: HomeAssistant,
|
||||
hass_client_no_auth: ClientSessionGenerator,
|
||||
init_integration,
|
||||
firmware_dir: Path,
|
||||
) -> None:
|
||||
path = firmware_dir / "a.img"
|
||||
path.write_bytes(build_image())
|
||||
registry = hass.data[DATA_SHARED].registry
|
||||
other = firmware_dir / "b.img"
|
||||
other.write_bytes(build_image(version="0.3.9-rc1"))
|
||||
key = registry.create(path)
|
||||
mine = build_image()
|
||||
other = build_image(version="0.3.9-rc1")
|
||||
key = registry.create(mine)
|
||||
other_key = registry.create(other)
|
||||
client = await hass_client_no_auth()
|
||||
|
||||
response = await client.get(f"/api/ninlight/firmware/{key}")
|
||||
assert response.status == 200
|
||||
assert await response.read() == path.read_bytes()
|
||||
assert await response.read() == mine
|
||||
|
||||
other_response = await client.get(f"/api/ninlight/firmware/{other_key}")
|
||||
assert other_response.status == 200
|
||||
assert await other_response.read() == other
|
||||
|
||||
assert (await client.get("/api/ninlight/firmware/" + "x" * 43)).status == 404
|
||||
registry.revoke(key)
|
||||
assert (await client.get(f"/api/ninlight/firmware/{key}")).status == 404
|
||||
|
||||
|
||||
async def test_view_returns_404_when_file_vanished(
|
||||
hass: HomeAssistant,
|
||||
hass_client_no_auth: ClientSessionGenerator,
|
||||
init_integration,
|
||||
firmware_dir: Path,
|
||||
) -> None:
|
||||
key = hass.data[DATA_SHARED].registry.create(firmware_dir / "gone.img")
|
||||
client = await hass_client_no_auth()
|
||||
assert (await client.get(f"/api/ninlight/firmware/{key}")).status == 404
|
||||
# revoking one key never touches another registered under a different key
|
||||
assert (await client.get(f"/api/ninlight/firmware/{other_key}")).status == 200
|
||||
|
||||
|
||||
async def test_base_url_prefers_option(hass: HomeAssistant) -> None:
|
||||
|
||||
Reference in New Issue
Block a user