113 lines
7.4 KiB
Python
113 lines
7.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Verify the URL-fix evidence and publish a current index with explicit history."""
|
|
from datetime import datetime, timezone
|
|
import hashlib
|
|
import json
|
|
from pathlib import Path
|
|
import xml.etree.ElementTree as ET
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
RESULTS = ROOT / 'tests/results/portal'
|
|
|
|
|
|
def sha(path):
|
|
with path.open('rb') as stream:
|
|
return hashlib.file_digest(stream, 'sha256').hexdigest()
|
|
|
|
|
|
def read(name):
|
|
return json.loads((RESULTS / name).read_text())
|
|
|
|
|
|
def main():
|
|
builds = {name: read(name + '-build-record.json') for name in ('arch', 'ubuntu')}
|
|
current_sources = {str(path.relative_to(ROOT)): sha(path) for directory in ('src', 'qml', 'cmake', 'resources')
|
|
for path in (ROOT / directory).rglob('*') if path.is_file() and '__pycache__' not in path.parts}
|
|
current_sources.update({name: sha(ROOT / name) for name in ('CMakeLists.txt', 'resources.qrc')})
|
|
for name, value in builds.items():
|
|
assert all(value['sourceSha256'].get(path) == digest for path, digest in current_sources.items())
|
|
for path in ('tests/test_web_qml.cpp', 'tests/webqml/tst_reader.qml'):
|
|
assert value['sourceSha256'][path] == sha(ROOT / path)
|
|
ctest = RESULTS / (name + '-ctest')
|
|
assert sha(ctest / 'tests.xml') == value['ctest']['junitSha256']
|
|
assert sha(ctest / 'LastTest.log') == value['ctest']['logSha256']
|
|
cases = ET.parse(ctest / 'tests.xml').findall('.//testcase')
|
|
assert len(cases) == 22 and all(row.find('failure') is None and row.find('skipped') is None for row in cases)
|
|
assert all(sha(ROOT / 'build' / name) == digest for name, digest in builds['arch']['binaries'].items())
|
|
package = read('ubuntu-package/report.json')
|
|
repeated = read('ubuntu-package/repeat-report.json')
|
|
verified = read('ubuntu-package/verification.json')
|
|
archive = ROOT / 'build-ubuntu-vm/packages' / package['archive']
|
|
assert package['success'] and repeated['success'] and verified['success']
|
|
assert package['archiveSha256'] == repeated['archiveSha256'] == sha(archive)
|
|
assert verified['archiveSha256'] == package['archiveSha256']
|
|
assert verified['allSizesModesAndHashesMatch'] and verified['rootOwnership']
|
|
assert verified['filesVerified'] == package['payloadFiles']
|
|
assert package['packagerSha256'] == sha(ROOT / 'tools/package_ubuntu.py')
|
|
assert package['executableSha256'] == builds['ubuntu']['installedBinaries']
|
|
assert package['manifestSha256'] == sha(RESULTS / 'ubuntu-package/package-manifest.json')
|
|
portal = {}
|
|
for platform, directory in {'x11': 'portal-x11-final', 'wayland': 'portal-wayland-fixed-keymap'}.items():
|
|
report = read(directory + '/report.json')
|
|
assert report['success'] and report['executablesUnchanged'] and not report['remainingTaggedChildren']
|
|
assert report['executables'] == package['executableSha256']
|
|
assert report['packageManifestSha256'] == package['manifestSha256']
|
|
assert report['runnerSha256'] == sha(RESULTS / directory / 'runner-at-start.py')
|
|
assert report['portalResponses'] == ['2', '0', '0', '0', '0']
|
|
assert [row['case'] for row in report['cases']] == ['cancel', 'pdf', 'html', 'htmlzip', 'epub']
|
|
assert all(row['focusRestored'] for row in report['cases'])
|
|
portal[platform] = {key: report[key] for key in ('success', 'platform', 'executables', 'portalResponses', 'cases', 'scope')}
|
|
lifecycle = {phase: read('package-vm/' + phase + '/report.json') for phase in ('install', 'smoke', 'remove')}
|
|
assert all(row['success'] and row['archiveSha256'] == package['archiveSha256'] for row in lifecycle.values())
|
|
assert lifecycle['install']['executables'] == package['executableSha256']
|
|
assert lifecycle['install']['installationMode'] == 'upgrade'
|
|
assert lifecycle['install']['runnerSha256'] == sha(ROOT / 'tests/ubuntu_vm/clean_package.py')
|
|
assert lifecycle['smoke']['smokeConditions'] == 12
|
|
assert lifecycle['remove']['payloadRemoved'] and lifecycle['remove']['kernelRestrictionUnchanged']
|
|
performance = read('performance-suite/summary.json')
|
|
assert performance['success'] and len(performance['cases']) == 10
|
|
assert all(builds['arch']['binaries'][name] == digest for name, digest in performance['buildSha256'].items())
|
|
for row in performance['cases']:
|
|
assert sha(RESULTS / 'performance-suite' / row['record']) == row['recordSha256']
|
|
assert performance['interactionRecordSha256'] == sha(RESULTS / 'performance-suite/interaction/record.json')
|
|
assert performance['stressRecordSha256'] == sha(RESULTS / 'performance-suite/stress/report.json')
|
|
prior = read('prior-validation-record.json')
|
|
record = {
|
|
'schemaVersion': 2, 'recordedAtUtc': datetime.now(timezone.utc).isoformat(),
|
|
'scope': 'Current URL-fix build: Arch/Ubuntu full CTest, Ubuntu package and XDG/GTK file chooser integration; Arch ten-condition performance, interaction and 1 GiB PDF stress',
|
|
'ctestSkipScope': 'All 22 CTest groups pass. Each App group explicitly skips its opt-in performance case; Ubuntu Python 3.12 skips 5 zstd provenance cases. These are not counted as executed acceptance tests.',
|
|
'goalComplete': False, 'sourceSha256': current_sources,
|
|
'validationToolsSha256': {name: sha(ROOT / name) for name in (
|
|
'tests/portal/record_build.py', 'tests/portal/record_validation.py', 'tests/portal/run.py',
|
|
'tests/portal/run_performance.py', 'tests/portal/summarize_performance.py', 'tests/ubuntu_vm/clean_package.py')},
|
|
'executables': {name: builds['arch']['binaries'][name] for name in package['executableSha256']},
|
|
'builds': builds, 'ubuntuPackage': package, 'portal': portal,
|
|
'packageLifecycle': lifecycle,
|
|
'performance': performance,
|
|
'historicalEvidence': {
|
|
'record': 'tests/results/portal/prior-validation-record.json',
|
|
'sha256': sha(RESULTS / 'prior-validation-record.json'),
|
|
'changedCompiledSources': [name for name, digest in current_sources.items() if prior['sourceSha256'].get(name) != digest],
|
|
'unchangedArchWorkers': [name for name in ('docview-pdf-worker', 'docview-archive-worker')
|
|
if prior['executables'][name] == builds['arch']['binaries'][name]],
|
|
'scope': 'Prior full-app performance, GPU, IME, high-density PDF and package measurements are versioned history. Current ten-condition performance and 1 GiB stress are recorded separately above.',
|
|
},
|
|
'remainingAcceptance': [
|
|
'Windows 11 native MSVC/Qt build, LPAC/pipe/PE execution and installer',
|
|
'Target-OS physical GPU/display/input, reference hardware and long-duration acceptance',
|
|
'Human G-RENDER reference-image approval',
|
|
'Complete notices/corresponding sources, public license and release distribution decision',
|
|
],
|
|
'evidenceSha256': {str(path.relative_to(ROOT)): sha(path) for path in sorted(RESULTS.rglob('*'))
|
|
if path.is_file() and path.suffix != '.pyc' and path != RESULTS / 'record.json'},
|
|
}
|
|
encoded = json.dumps(record, ensure_ascii=False, indent=2) + '\n'
|
|
(RESULTS / 'record.json').write_text(encoded)
|
|
(ROOT / 'docs/validation-record.json').write_text(encoded)
|
|
print(json.dumps({'archCtestGroups': 22, 'ubuntuCtestGroups': 22, 'portalCases': 10,
|
|
'packageSmokeConditions': 12, 'performanceConditions': 10, 'goalComplete': False}))
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|