feat(ppclock): SUOTA 固件升级(ota.py + CLI ota 子命令 + 预检),APK互证报告入库,123 测试全绿
This commit is contained in:
1 parent
7079053dde
commit
3b92c382fc
7 files changed
+443
No files matched your search
@@ -191,3 +191,18 @@ class TestBatch:
|
||||
code, out = run_cli(capsys, ["--json", "batch", str(f), "--stop-on-error"])
|
||||
results = out["data"]["results"]
|
||||
assert len(results) == 1 and results[0]["ok"] is False
|
||||
|
||||
|
||||
class TestOta:
|
||||
def test_ota_precheck_without_yes(self, capsys):
|
||||
code, out = run_cli(capsys, ["--json", "ota", "app/firmware-PP_da14585_4.2_CH.img"])
|
||||
assert code == 0
|
||||
assert out["data"]["precheck"] == "ok"
|
||||
assert out["data"]["body_size"] == 72164
|
||||
|
||||
def test_ota_rejects_bad_file(self, capsys, tmp_path):
|
||||
bad = tmp_path / "bad.img"
|
||||
bad.write_bytes(b"\x00" * 128)
|
||||
code, out = run_cli(capsys, ["--json", "ota", str(bad)])
|
||||
assert code == 1
|
||||
assert out["ok"] is False
|
||||
@@ -0,0 +1,54 @@
|
||||
"""OTA/SUOTA 打包逻辑测试(证据:analysis/apk/apk-analysis.md §e,z7.h0/z7.b0)。"""
|
||||
import pytest
|
||||
|
||||
from ppclock import ota
|
||||
|
||||
|
||||
class TestPackaging:
|
||||
def test_xor_checksum(self):
|
||||
assert ota.xor_checksum(bytes([0x01, 0x02, 0x03])) == 0x00
|
||||
assert ota.xor_checksum(bytes([0xFF, 0x0F])) == 0xF0
|
||||
assert ota.xor_checksum(b"") == 0
|
||||
|
||||
def test_package_appends_xor_byte(self):
|
||||
img = bytes([0xAA] * 240)
|
||||
blocks = ota.package_image(img)
|
||||
total = b"".join(blocks)
|
||||
assert len(total) == 241
|
||||
assert total[-1] == 0x00 # 240×0xAA(偶数个)XOR = 0
|
||||
assert ota.xor_checksum(total) == 0 # 含校验字节后全镜像 XOR 为 0
|
||||
|
||||
def test_package_xor_byte_odd(self):
|
||||
img = bytes([0xAA] * 241)
|
||||
total = b"".join(ota.package_image(img))
|
||||
assert total[-1] == 0xAA # 奇数个
|
||||
assert ota.xor_checksum(total) == 0
|
||||
|
||||
def test_block_size_default_240(self):
|
||||
blocks = ota.package_image(bytes(240 * 3 + 10))
|
||||
assert [len(b) for b in blocks] == [240, 240, 240, 11]
|
||||
|
||||
def test_patch_len_encoding(self):
|
||||
assert ota.patch_len_frame(240) == (240).to_bytes(2, "little")
|
||||
|
||||
def test_signals(self):
|
||||
assert ota.MEM_DEV_SPI_FLASH == bytes([0x00, 0x00, 0x00, 0x13])
|
||||
assert ota.GPIO_MAP_DEFAULT == bytes([0x00, 0x00, 0x06, 0x05])
|
||||
assert ota.END_SIGNAL == bytes([0x00, 0x00, 0x00, 0xFE])
|
||||
assert ota.REBOOT_SIGNAL == bytes([0x00, 0x00, 0x00, 0xFD])
|
||||
|
||||
def test_write_chunk_split(self):
|
||||
"""240B 块按 MTU-3=20B 写块切分"""
|
||||
block = bytes(range(240))
|
||||
chunks = list(ota.write_chunks(block, 20))
|
||||
assert len(chunks) == 12
|
||||
assert b"".join(chunks) == block
|
||||
|
||||
|
||||
class TestStatusCodes:
|
||||
def test_status_ok(self):
|
||||
assert ota.STATUS_OK == 2
|
||||
|
||||
def test_error_table_has_crc_error(self):
|
||||
assert 4 in ota.STATUS_ERRORS
|
||||
assert "CRC" in ota.STATUS_ERRORS[4]
|
||||
Reference in new issue
Block a user