Files
2026-09-21 13:41:40 +09:00

119 lines
8.2 KiB
Python

#!/usr/bin/env python3
"""Bind a notice-only Ubuntu package update to the existing tested executables."""
from datetime import datetime, timezone
import hashlib
import json
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2]
RESULTS = ROOT / 'tests/results/qt-notice-supplement'
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():
prior = read('prior-validation-record.json')
assert sha(RESULTS / 'prior-validation-record.json') == '25bc879e35e02b70f7bd1cf2afca293896afb247163fa5b1f81020ec5bd3359b'
for name, digest in prior['evidenceSha256'].items():
assert sha(ROOT / name) == digest, name
assert sha(RESULTS / 'prior-packager.py') == prior['ubuntuPackage']['packagerSha256']
assert sha(RESULTS / 'prior-record-validation.py') == prior['validationToolsSha256']['tests/portal/record_validation.py']
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')})
assert current_sources == prior['sourceSha256']
for name, digest in prior['builds']['arch']['binaries'].items():
assert sha(ROOT / 'build' / name) == digest
supplement = read('collection/report.json')
repeat = read('collection-repeat/report.json')
assert supplement == repeat and supplement['success']
assert len(supplement['files']) == 6 and len(supplement['notices']) == 2
assert supplement['collectorSha256'] == sha(ROOT / 'tests/source_archives/collect_qt_sdk_supplement.py')
assert supplement['baseNoticeReportSha256'] == sha(ROOT / 'tests/results/source-archives/qt-sdk-notices-final/report.json')
for row in supplement['files']:
assert sha(RESULTS / 'collection' / row['file']) == row['sha256']
assert sha(RESULTS / 'collection-repeat' / row['file']) == row['sha256']
package = read('package/report.json')
repeated = read('package/repeat-report.json')
verified = read('package/verification.json')
manifest = read('package/package-manifest.json')
assert package['success'] and repeated['success'] and verified['success']
assert package['archiveSha256'] == repeated['archiveSha256'] == verified['archiveSha256']
assert package['archiveSha256'] == sha(ROOT / 'build-ubuntu-vm/packages' / package['archive'])
assert package['manifestSha256'] == verified['packageManifestSha256'] == sha(RESULTS / 'package/package-manifest.json')
assert package['packagerSha256'] == sha(ROOT / 'tools/package_ubuntu.py')
assert package['collectorSha256'] == sha(ROOT / 'tools/collect_ubuntu_validation_runtime.py')
assert package['runtimeRecordSha256'] == sha(RESULTS / 'package/runtime/runtime.json')
assert package['executableSha256'] == prior['ubuntuPackage']['executableSha256']
assert package['executableSha256'] == prior['builds']['ubuntu']['installedBinaries']
assert verified['filesVerified'] == package['payloadFiles'] == len(manifest['files']) + 1
assert verified['allSizesModesAndHashesMatch'] and verified['rootOwnership']
assert package['sdkSupplementReportSha256'] == sha(RESULTS / 'collection/report.json')
assert manifest['sdkSupplementReportSha256'] == package['sdkSupplementReportSha256']
old_manifest = json.loads((ROOT / 'tests/results/portal/ubuntu-package/package-manifest.json').read_text())
old_rows = {r['path']: r for r in old_manifest['files']}
new_rows = {r['path']: r for r in manifest['files']}
added = sorted(new_rows.keys() - old_rows.keys())
removed = sorted(old_rows.keys() - new_rows.keys())
changed = sorted(name for name in old_rows.keys() & new_rows.keys() if old_rows[name] != new_rows[name])
assert not removed and len(added) == 7
assert all(name.startswith('opt/docview/share/doc/docview/third-party/qt-sdk-supplement/') for name in added)
assert changed == ['DEBIAN/control', 'opt/docview/share/doc/docview/UBUNTU-PACKAGE.txt']
for row in supplement['files']:
name = 'opt/docview/share/doc/docview/third-party/qt-sdk-supplement/' + row['file']
assert new_rows[name]['sha256'] == row['sha256'] and new_rows[name]['size'] == row['bytes']
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())
for phase, report in lifecycle.items():
assert report['runnerSha256'] == sha(ROOT / 'tests/ubuntu_vm/clean_package.py')
for command in report['commands']:
assert command['exitCode'] == 0
assert sha(RESULTS / 'package-vm' / phase / (command['name'] + '.log')) == command['logSha256']
assert lifecycle['install']['executables'] == package['executableSha256']
assert lifecycle['install']['installationMode'] == 'fresh-install'
assert lifecycle['install']['installedFilesVerified'] == len(manifest['files']) - 4
assert lifecycle['smoke']['smokeConditions'] == 12 and lifecycle['smoke']['executableBytesUnchanged']
assert lifecycle['remove']['payloadRemoved'] and lifecycle['remove']['kernelRestrictionUnchanged']
assert len(lifecycle['remove']['userProbesPreserved']) == 4
for os_name in ('arch', 'ubuntu'):
log = (RESULTS / ('package-tests-' + os_name + '.log')).read_text()
assert 'Ran 8 tests' in log and log.rstrip().endswith('OK')
assert read('shutdown.json')['allGuestsStopped']
record = {**prior, 'schemaVersion': 3, 'recordedAtUtc': datetime.now(timezone.utc).isoformat(),
'scope': 'Notice-only Ubuntu validation3 package; all compiled product sources and executables unchanged '
'from the URL-fix record. Eight packaging tests on Arch and Ubuntu, two identical deb builds, '
'archive verification and 12 X11/Wayland launches plus install/remove/purge on the existing SDK-free VM.',
'ubuntuPackage': package, 'packageLifecycle': lifecycle,
'noticeSupplement': supplement,
'packageChanges': {'added': added, 'removed': removed, 'changed': changed,
'selfManifestAlsoChanged': True, 'allOtherPayloadIdentical': True},
'previousValidation': {'record': 'tests/results/qt-notice-supplement/prior-validation-record.json',
'sha256': sha(RESULTS / 'prior-validation-record.json'),
'scope': 'All 22 CTest groups per OS, native portal cases and performance stay bound '
'to their original runs. Product bytes are unchanged. Portal ran on package '
'validation2; its OS integration was not rerun for notice-only validation3.'},
'packageVmScope': 'Existing dedicated Ubuntu 24.04 VM with no SDK/build tree. Test helpers already '
'installed; this is not a newly created OS. Prior validation1 fresh-OS evidence is historical.',
'validationToolsSha256': {**prior['validationToolsSha256'], **{name: sha(ROOT / name) for name in (
'tools/package_ubuntu.py', 'tools/verify_ubuntu_package.py', 'tests/test_ubuntu_package.py',
'tests/source_archives/collect_qt_sdk_supplement.py', 'tests/source_archives/record_qt_supplement.py')}},
'evidenceSha256': {**prior['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'}}, 'goalComplete': False}
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({'additionalNoticeFiles': 2, 'packageFiles': package['payloadFiles'],
'smokeConditions': 12, 'compiledSourcesUnchanged': True, 'goalComplete': False}))
if __name__ == '__main__':
main()