Files
Cognitive_Agent/tests/e2e/test_firmware_ota_server.py

113 lines
4.7 KiB
Python

from __future__ import annotations
import hashlib
import json
import threading
import urllib.request
from http.server import ThreadingHTTPServer
from pathlib import Path
from cognitive_agent.firmware_ota_server import FirmwareOtaHandler, FirmwareOtaRepository
class TestFirmwareOtaServer:
def test_latest_download_head_and_resume_are_read_only(self, tmp_path: Path) -> None:
release_id = "fw-rel-123456789abc"
filename = "PassengerSeat_test.zip"
package = (b"vehicle-firmware-package" * 128) + b"end"
release_root = tmp_path / "releases" / release_id
release_root.mkdir(parents=True)
package_path = release_root / filename
package_path.write_bytes(package)
manifest = {
"schema": "n7-ota-release/v1",
"release_id": release_id,
"firmware_filename": filename,
"size_bytes": len(package),
"sha256": hashlib.sha256(package).hexdigest(),
"capabilities": ["时间控制", "座椅加热"],
"published_at": "2026-09-16T13:17:17+08:00",
"status": "published",
"download_url": "http://stale-address.invalid/download",
}
(release_root / "release.json").write_text(
json.dumps(manifest, ensure_ascii=False), encoding="utf-8"
)
(tmp_path / "latest.json").write_text(
json.dumps(manifest, ensure_ascii=False), encoding="utf-8"
)
older_release_id = "fw-rel-000000000001"
older_root = tmp_path / "releases" / older_release_id
older_root.mkdir(parents=True)
older_filename = "PassengerSeat_older.zip"
older_package = b"older-firmware-package"
(older_root / older_filename).write_bytes(older_package)
older_manifest = {
**manifest,
"release_id": older_release_id,
"firmware_filename": older_filename,
"size_bytes": len(older_package),
"sha256": hashlib.sha256(older_package).hexdigest(),
"published_at": "2026-09-15T13:17:17+08:00",
}
(older_root / "release.json").write_text(
json.dumps(older_manifest, ensure_ascii=False), encoding="utf-8"
)
class Handler(FirmwareOtaHandler):
repository = FirmwareOtaRepository(
tmp_path, "https://n7-ota.example.ts.net/api/firmware-workbench/releases"
)
server = ThreadingHTTPServer(("127.0.0.1", 0), Handler)
thread = threading.Thread(target=server.serve_forever, daemon=True)
thread.start()
base_url = f"http://127.0.0.1:{server.server_port}"
try:
with urllib.request.urlopen(
f"{base_url}/api/firmware-workbench/releases/latest", timeout=3
) as response:
latest = json.loads(response.read().decode("utf-8"))
assert latest["download_url"] == (
f"https://n7-ota.example.ts.net/api/firmware-workbench/releases/"
f"{release_id}/download"
)
with urllib.request.urlopen(
f"{base_url}/api/firmware-workbench/releases", timeout=3
) as response:
releases = json.loads(response.read().decode("utf-8"))
assert releases["schema"] == "n7-ota-release-list/v1"
assert releases["count"] == 2
assert releases["latest_release_id"] == release_id
assert [item["release_id"] for item in releases["releases"]] == [
release_id,
older_release_id,
]
assert releases["releases"][1]["download_url"].endswith(
f"/{older_release_id}/download"
)
request = urllib.request.Request(
f"{base_url}/api/firmware-workbench/releases/{release_id}/download",
headers={"Range": "bytes=8-31"},
)
with urllib.request.urlopen(request, timeout=3) as response:
assert response.status == 206
assert response.headers["Content-Range"] == f"bytes 8-31/{len(package)}"
assert response.headers["X-Firmware-SHA256"] == manifest["sha256"]
assert response.read() == package[8:32]
head = urllib.request.Request(
f"{base_url}/api/firmware-workbench/releases/{release_id}/download",
method="HEAD",
)
with urllib.request.urlopen(head, timeout=3) as response:
assert response.status == 200
assert int(response.headers["Content-Length"]) == len(package)
assert response.read() == b""
finally:
server.shutdown()
server.server_close()
thread.join(timeout=3)