import hashlib import subprocess import sys from pathlib import Path SCRIPT = Path(__file__).with_name("nl_mkimage.py") def build(tmp_path, payload=b"\x01\x02\x03" * 100, device="evk", version="1.2.3"): src = tmp_path / "fw_gz.img" src.write_bytes(payload) out = tmp_path / "fw_ota.img" subprocess.run( [sys.executable, str(SCRIPT), "--image", str(src), "--device", device, "--version", version, "--out", str(out)], check=True, ) return src, out def test_appends_512_byte_trailer(tmp_path): src, out = build(tmp_path) data = out.read_bytes() assert len(data) == len(src.read_bytes()) + 512 assert data[: len(src.read_bytes())] == src.read_bytes() trailer = data[-512:] assert trailer[0:4] == b"NINL" assert trailer[4] == 1 assert trailer[5:21].rstrip(b"\x00") == b"evk" assert trailer[21:37].rstrip(b"\x00") == b"1.2.3" assert trailer[37:69] == hashlib.sha256(src.read_bytes()).digest() assert set(trailer[69:]) == {0xFF} def test_rejects_long_fields(tmp_path): src = tmp_path / "fw_gz.img" src.write_bytes(b"x") r = subprocess.run( [sys.executable, str(SCRIPT), "--image", str(src), "--device", "0123456789abcdef", "--version", "1", "--out", str(tmp_path / "o.img")], capture_output=True, text=True, ) assert r.returncode != 0 assert "device" in r.stderr def test_refuses_image_that_already_has_a_trailer(tmp_path): _, out = build(tmp_path) r = subprocess.run( [sys.executable, str(SCRIPT), "--image", str(out), "--device", "evk", "--version", "1.2.3", "--out", str(tmp_path / "again.img")], capture_output=True, text=True, ) assert r.returncode != 0 assert "trailer" in r.stderr def verify(path, *extra): return subprocess.run( [sys.executable, str(SCRIPT), "--verify", str(path), *extra], capture_output=True, text=True, ) def test_verify_accepts_a_good_image(tmp_path): _, out = build(tmp_path, device="e27_rgb", version="1.2.3") r = verify(out) assert r.returncode == 0, r.stderr assert r.stdout.split()[:2] == ["e27_rgb", "1.2.3"] def test_verify_rejects_a_file_without_trailer(tmp_path): p = tmp_path / "plain.img" p.write_bytes(b"x" * 5000) r = verify(p) assert r.returncode == 1 assert "trailer" in r.stderr.lower() def test_verify_rejects_a_corrupted_payload(tmp_path): _, out = build(tmp_path) d = bytearray(out.read_bytes()) d[100] ^= 0x01 out.write_bytes(d) r = verify(out) assert r.returncode == 1 assert "sha256" in r.stderr.lower() def test_verify_checks_the_expected_device(tmp_path): _, out = build(tmp_path, device="evk") assert verify(out, "--expect-device", "evk").returncode == 0 r = verify(out, "--expect-device", "g95_cw") assert r.returncode == 1 assert "evk" in r.stderr and "g95_cw" in r.stderr def test_verify_rejects_a_file_shorter_than_the_trailer(tmp_path): p = tmp_path / "tiny.img" p.write_bytes(b"NINL" + b"\x00" * 10) r = verify(p) assert r.returncode == 1