import hashlib import json import subprocess import xml.etree.ElementTree as ET from pathlib import Path root = Path('C:/git/MagnetismHeroes') proof = root / 'artifacts/verification/VisualUpgrade/FinalProduct' final = root / 'artifacts/verification/Final' def read(path): return json.loads(path.read_text(encoding='utf-8-sig')) def sha(path): return hashlib.sha256(path.read_bytes()).hexdigest().upper() completion = read(proof / 'completion.json') source = '3346eb559bdfba24332feb4d9be4b7104520233e' assert completion['status'] == 'passed' and completion['sourceCommit'] == source assert len(completion['phases']) == 4 and completion['productHashesUnchanged'] for phase in completion['phases']: assert phase['exitCode'] == 0 and phase['status'] == 'passed' assert phase['sourceCommit'] == source and phase['sourceDirty'] is False and phase['sourceDirtyEnd'] is False raw = read(Path(phase['evidence'])) assert raw['status'] == 'passed' and raw['exitCode'] == 0 and raw['sourceCommit'].strip() == source counts = {} for mode, count in [('editmode', 103), ('playmode', 53)]: cases = ET.parse(final / (mode + '.xml')).findall('.//test-case') assert len(cases) == count and all(case.get('result') == 'Passed' for case in cases) counts[mode] = count apk_hash = sha(root / 'artifacts/android/Final/MagnetismHeroes.apk') assert sha(root / 'artifacts/android/MagnetismHeroes.apk') == apk_hash for path, count in [ ('android-final-evidence.json', 226), ('Fresh30/android-final-progression-evidence.json', 151), ('FinalBoundary/android-final-boundary-evidence.json', 37), ('RapidBoundary/android-final-rapid-evidence.json', 39), ('ContentBoundary/android-content-evidence.json', 69), ]: data = read(final / path) assert data['status'] == 'passed' and data['sourceCommit'].strip() == source assert data['apkSha256'].upper() == apk_hash and data['sourceDirty'] is False assert len(data['checks']) == count and all(check['passed'] for check in data['checks']) counts[path] = count before = read(proof / 'product-before.json') after = read(proof / 'product-after.json') assert before == after and len(before) == 732 assert all(sha(root / path) == digest.upper() for path, digest in before.items()) assert subprocess.check_output(['git', 'status', '--porcelain'], cwd=root).strip() == b'' assert subprocess.check_output(['git', 'rev-parse', 'dev'], cwd=root).decode().strip() == '58410281e015c6600dc543c4e093fd95c036288c' for failure in completion.get('failedAttempts', []): assert failure['exitCode'] == 1 and failure['status'] == 'failed' archived = read(Path(failure['evidence'])) assert archived['exitCode'] == 1 and archived['status'] == 'failed' assert Path(failure['outerLog']).is_file() report = {'status': 'PASS', 'testedProductSourceCommit': source, 'currentHead': subprocess.check_output(['git', 'rev-parse', 'HEAD'], cwd=root).decode().strip(), 'counts': counts, 'apkSha256': apk_hash, 'productFileHashesUnchanged': len(before), 'failedAttemptsPreserved': len(completion.get('failedAttempts', [])), 'protectedDevUnchanged': True} (proof / 'root-final-product-audit.json').write_text(json.dumps(report, indent=2) + '\n', encoding='utf-8') print(json.dumps(report))