"""OTA/SUOTA 打包逻辑测试(证据:analysis/apk/apk-analysis.md §e,z7.h0/z7.b0)。""" import pytest from ppclock.firmware 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]