Files
kefu/deploy/single-instance-tray-20260917/verify_frozen_release.py
T
2026-09-21 10:34:06 +08:00

38 lines
2.7 KiB
Python

from pathlib import Path
import hashlib,json,os,sys,tempfile,types
from unittest import mock
from PyInstaller.archive.readers import CArchiveReader
root=Path('C:/wechat_rpa')
folder=Path('C:/kefu/deploy/single-instance-tray-20260917')
app=root/'dist/ZhenAI-WeCom-Assistant-v1.4.21'
exe=app/'ZhenAI-WeCom-Assistant-v1.4.21.exe'
manifest=json.loads((folder/'build-source-manifest.json').read_text(encoding='utf-8'))
assert sys.version_info[:2]==(3,12)
assert all(hashlib.sha256((root/name).read_bytes()).hexdigest()==digest for name,digest in manifest.items())
archive=CArchiveReader(str(exe));pyz=archive.open_embedded_archive('PYZ.pyz')
sender=pyz.extract('wecom_native_sender')
functions={item.co_name:item for item in sender.co_consts if isinstance(item,types.CodeType)}
needed=['_file_identity','_path_file_identity','_hash_client_file']
assert all(name in functions for name in needed)
assert 'stat' not in functions['_path_file_identity'].co_names
assert 'fstat' in functions['_path_file_identity'].co_names
assert '_path_file_identity' in functions['_hash_client_file'].co_names
env={'Path':Path,'os':os,'hashlib':hashlib,'NativeUnavailable':type('NativeUnavailable',(RuntimeError,),{})}
for name in needed:env[name]=types.FunctionType(functions[name],env)
with tempfile.TemporaryDirectory(prefix='frozen-identity-',dir=folder) as temp:
p=Path(temp)/'fixture.bin';content=b'packaged file identity regression\x00'*4096;p.write_bytes(content)
os.utime(p,ns=(1_600_000_000_000_000_000,1_600_000_000_000_000_000))
with mock.patch.object(Path,'stat',side_effect=AssertionError('Path.stat must not be used for handle identity')):
actual,identity=env['_hash_client_file'](p)
assert actual==hashlib.sha256(content).hexdigest()
assert identity[2]==len(content)
private={'wxwork_keys.json','protocol_sends.sqlite3','pending_replies.protocol.json','pending_replies.json','conversations.json','backend_connection.json','runtime_settings.json','desktop_account.json'}
assert not any(p.name in private for p in app.rglob('*') if p.is_file())
for relative in ['assets/ui/console-app.js','assets/ui/zhenyang-ai-console.html','assets/ui/console-review.css','assets/ui/console-responsive.css']:
assert (app/'_internal'/relative).read_bytes()==(root/relative).read_bytes(),relative
assert (app/'_internal/python312.dll').is_file()
report={'version':'1.4.21','sourceManifestMatches':True,'frozenFileIdentityFixPresent':True,'frozenHashSyntheticRegression':'passed','python312Bundled':True,'privateFilesExcluded':True,'uiAssetsMatchSource':True,'runtime':sys.version,'realMessagesSent':0,'installed':False}
(folder/'frozen-release-qa.json').write_text(json.dumps(report,ensure_ascii=False,indent=2),encoding='utf-8')
print(json.dumps(report,ensure_ascii=False))