107 lines
5.9 KiB
Python
107 lines
5.9 KiB
Python
#!/usr/bin/env python3
|
|
"""Run corrected RI, transparency and original CMYK probes plus DocView CTest."""
|
|
import argparse
|
|
import hashlib
|
|
import json
|
|
import os
|
|
from pathlib import Path
|
|
import platform
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
import time
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
|
|
|
|
def sha(path):
|
|
with path.open('rb') as stream:
|
|
return hashlib.file_digest(stream, 'sha256').hexdigest()
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument('--library', type=Path, required=True)
|
|
parser.add_argument('--build-dir', type=Path, required=True)
|
|
parser.add_argument('--output', type=Path, required=True)
|
|
args = parser.parse_args()
|
|
library, build = args.library.resolve(), args.build_dir.resolve()
|
|
binaries = [library, ROOT / '.deps/pdfium/lib/libpdfium.so'] + [build / name for name in
|
|
('docview', 'docview-pdf-worker', 'docview-archive-worker', 'pdf-worker-evidence')]
|
|
identities = {str(path): sha(path) for path in binaries}
|
|
environment = os.environ.copy()
|
|
assert not environment.get('LD_PRELOAD') and not environment.get('LD_AUDIT')
|
|
assert not environment.get('QTWEBENGINE_DISABLE_SANDBOX')
|
|
environment.pop('WAYLAND_DISPLAY', None)
|
|
environment.update(LD_LIBRARY_PATH=str(library.parent) + (
|
|
':' + environment['LD_LIBRARY_PATH'] if environment.get('LD_LIBRARY_PATH') else ''),
|
|
QT_QPA_PLATFORM='xcb', QT_QUICK_BACKEND='software',
|
|
QTWEBENGINE_CHROMIUM_FLAGS='--disable-gpu', QT_SCALE_FACTOR='1',
|
|
QT_AUTO_SCREEN_SCALE_FACTOR='0', XDG_SESSION_TYPE='x11')
|
|
output = args.output.resolve()
|
|
output.mkdir(parents=True, exist_ok=False)
|
|
report = {'schemaVersion': 1, 'candidateTestsPass': False, 'acceptanceComplete': False,
|
|
'platform': platform.platform(), 'osRelease': platform.freedesktop_os_release(),
|
|
'inputs': identities, 'runnerSha256': sha(Path(__file__)), 'commands': [],
|
|
'productionDependencyReplaced': False,
|
|
'scope': 'Fixed candidate selected only for this test process tree. Generated fixtures and corrected stream-entry RI expectations; no physical display, Windows, human golden or release acceptance.'}
|
|
|
|
def run(label, command):
|
|
start = time.monotonic()
|
|
log = output / (label + '.log')
|
|
with log.open('w') as stream:
|
|
result = subprocess.run(command, cwd=ROOT, env=environment,
|
|
stdout=stream, stderr=subprocess.STDOUT, timeout=900)
|
|
report['commands'].append({'name': label, 'command': command,
|
|
'exitCode': result.returncode, 'seconds': time.monotonic() - start,
|
|
'logSha256': sha(log)})
|
|
print(label, result.returncode, flush=True)
|
|
return result.returncode
|
|
|
|
try:
|
|
linked = subprocess.run(['ldd', str(build / 'docview-pdf-worker')], env=environment,
|
|
capture_output=True, text=True, check=True).stdout
|
|
assert str(library) in linked and 'not found' not in linked
|
|
(output / 'worker-ldd.txt').write_text(linked)
|
|
run('cmyk', [sys.executable, str(ROOT / 'tests/cmyk_lut/run.py'),
|
|
'--build-dir', str(build), '--output', str(output / 'cmyk')])
|
|
run('intents', [sys.executable, str(ROOT / 'tests/cmyk_lut/intents.py'),
|
|
'--build-dir', str(build), '--pdfium-library', str(library),
|
|
'--corpus', str(ROOT / 'tests/fixtures/pdf/rendering-intents-context'),
|
|
'--scales', '.5', '1', '4', '--output', str(output / 'intents')])
|
|
run('transparency', [sys.executable, str(ROOT / 'tests/cmyk_lut/transparency.py'),
|
|
'--build-dir', str(build), '--pdfium-library', str(library),
|
|
'--scales', '.5', '1', '2', '--output', str(output / 'transparency')])
|
|
ctest_status = run('ctest', ['xvfb-run', '-a', '-s', '-screen 0 1100x760x24',
|
|
'dbus-run-session', '--', 'ctest', '--test-dir', str(build),
|
|
'--output-on-failure', '--output-junit', str(output / 'tests.xml')])
|
|
shutil.copyfile(build / 'Testing/Temporary/LastTest.log', output / 'LastTest.log')
|
|
reports = {name: json.loads((output / name / 'report.json').read_text())
|
|
for name in ('cmyk', 'intents', 'transparency')}
|
|
report['cmykSuccess'] = reports['cmyk']['success']
|
|
report['correctedOracle'] = reports['intents']['oracleRevision'] == 2 and not reports['intents']['oracleKnownIssue']
|
|
for name in ('intents', 'transparency'):
|
|
data = reports[name]
|
|
report[name] = {key: data.get(key, False) for key in
|
|
('pdfiumSuccess', 'popplerSuccess', 'fixtureValidationSuccess', 'binariesUnchanged', 'originalUnchanged')}
|
|
report[name]['probeCount'] = sum(len(row['probes']) for row in data['scales'])
|
|
report['ctestSuccess'] = ctest_status == 0
|
|
report['allBinaryInputsUnchanged'] = all(sha(Path(path)) == value for path, value in identities.items())
|
|
report['candidateTestsPass'] = all((report['cmykSuccess'], report['correctedOracle'],
|
|
report['ctestSuccess'], report['allBinaryInputsUnchanged'], *[
|
|
report[name][key] for name in ('intents', 'transparency') for key in
|
|
('pdfiumSuccess', 'fixtureValidationSuccess', 'binariesUnchanged', 'originalUnchanged')]))
|
|
report['comparisonAgreement'] = all(report[name]['popplerSuccess'] for name in ('intents', 'transparency'))
|
|
finally:
|
|
report['evidenceSha256'] = {str(path.relative_to(output)): sha(path)
|
|
for path in sorted(output.rglob('*')) if path.is_file()}
|
|
(output / 'report.json').write_text(json.dumps(report, indent=2) + '\n')
|
|
print(json.dumps({key: report.get(key) for key in
|
|
('candidateTestsPass', 'comparisonAgreement', 'allBinaryInputsUnchanged', 'acceptanceComplete')}))
|
|
if not report['candidateTestsPass']:
|
|
raise SystemExit('Candidate regression failed; all individual outcomes are retained.')
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|