- src/ 人写代码:main.py(Fluent 界面、Light/Dark/dark1/dark2/跟随系统主题、 关于按钮;主题三件套 = setTheme + QPalette/应用级 QSS + DWM 标题栏, 修复 Light 下窗口背景/页签/标题栏仍为系统深色的问题)、edid.py (EDID/CTA/HDMI/HDR 解析)、windows_edid.py(WMI 只读)、theme.py、 test_edid.py(9 项解析测试,含随机畸形数据无崩溃检查) - assets/ 图标与生成脚本;release/ 交付:EDID-Viewer.exe(onefile 63.7MB, 启动/图标/主题已验证)+ README,与 DLPilot/release 同约定 exe 直接入库 - 流水线对齐 DLPilot:src/build_exe.py(spec 由脚本生成不入库,剔除 PATH 上 Poppler/Conda 版本化 ICU,避免 QtCore 报 WinError 127)→ package_release.py(组装 EDID-Viewer-v*-win64.zip,zip 只上传 Gitea)→ publish_gitea.py(token 走 GITEA_TOKEN,自签证书 --insecure) - agent.md 更名 AGENTS.md(DLPilot 双文档约定:README 给人 / AGENTS.md 给 Agent);根 .gitignore 增加 EDID-viewer/release/*.zip - validation/ 保留 EDID 本机/合成样本与窗口截图、关于对话框自检脚本
51 lines
2.6 KiB
Python
51 lines
2.6 KiB
Python
import random
|
||
import unittest
|
||
from edid import parse,dtd
|
||
|
||
def checksum(b):
|
||
b[127]=(-sum(b[:127]))&255
|
||
return bytes(b)
|
||
|
||
def base(ext=0):
|
||
b=bytearray(128); b[:8]=bytes.fromhex('00ffffffffffff00'); b[8:10]=bytes.fromhex('4c2d')
|
||
b[18:20]=bytes((1,4)); b[20]=0xa2; b[38:54]=b'\x01\x01'*8; b[126]=ext
|
||
b[54:72]=bytes.fromhex('023a801871382d40582c4500fd1e1100001e')
|
||
b[72:90]=b'\0\0\0\xfc\0TEST PANEL\n '
|
||
return bytearray(checksum(b))
|
||
|
||
class Tests(unittest.TestCase):
|
||
def test_identity_and_dtd(self):
|
||
r=parse(base()); self.assertEqual(r['基本信息']['显示器名称'],'TEST PANEL')
|
||
self.assertEqual(r['基本信息']['厂家 PNP 代码'],'SAM')
|
||
t=r['时序'][0]; self.assertEqual(t['分辨率'],'1920×1080p'); self.assertEqual(t['刷新率'],'60.000 Hz')
|
||
self.assertEqual(t['同步'],'H+ V+'); self.assertEqual(t['水平有效/前肩/同步/后肩'],[1920,88,44,148])
|
||
def test_standard(self):
|
||
b=base(); b[38:40]=bytes((129,192)); r=parse(checksum(b))
|
||
self.assertEqual(r['时序'][0]['分辨率'],'1280×720'); self.assertEqual(r['时序'][0]['刷新率'],'60 Hz')
|
||
def test_cta(self):
|
||
b=bytearray(128); payload=bytes.fromhex('429061 23090707 67030c0012343078 e3060c01')
|
||
b[:4]=bytes((2,3,4+len(payload),0x70)); b[4:4+len(payload)]=payload
|
||
r=parse(bytes(base(1))+checksum(b)); text=str(r)
|
||
self.assertIn('1.2.3.4',text); self.assertIn('PQ / ST 2084',text); self.assertIn('3840×2160p 60 Hz',text)
|
||
self.assertIn('600 MHz',text); self.assertIn('LPCM',text)
|
||
def test_missing_extension(self):
|
||
self.assertTrue(parse(base(2))['警告'])
|
||
def test_bad_checksum_and_header(self):
|
||
b=base(); b[0]=1; r=parse(b); self.assertTrue(r['警告']); self.assertIn('失败',r['校验'][0])
|
||
def test_bounds(self):
|
||
with self.assertRaises(ValueError): parse(b'\0'*127)
|
||
b=bytearray(128); b[:5]=bytes((2,3,6,0,0x5f))
|
||
self.assertIn('越界',str(parse(bytes(base(1))+checksum(b))['警告']))
|
||
def test_unknown_extension(self):
|
||
b=bytearray(128); b[0]=0x70
|
||
self.assertIn('暂未解码',str(parse(bytes(base(1))+checksum(b))))
|
||
def test_interlaced(self):
|
||
b=bytes.fromhex('011d8018711c1620582c2500fd1e1100009e')
|
||
t=dtd(b,'test'); self.assertEqual(t['分辨率'],'1920×1080i'); self.assertEqual(t['刷新率'],'60.000 Hz(场率)')
|
||
def test_random_malformed(self):
|
||
rng=random.Random(42)
|
||
for _ in range(1000):
|
||
b=bytearray(rng.randbytes(rng.randint(128,600))); b[18]=1; parse(b)
|
||
|
||
if __name__=='__main__': unittest.main()
|