summaryrefslogtreecommitdiff
path: root/tests/helpers/run_cocoa_bundle.py
diff options
context:
space:
mode:
authorBerke Güzel <wenekar1@gmail.com>2026-10-12 22:12:02 +0300
committerBerke Güzel <wenekar1@gmail.com>2026-10-12 22:12:02 +0300
commit94c5e361fbb229b0cd6853e2102a7d95f1f358b3 (patch)
tree3c0f11af9dcb84dac8067a31a6979acd6dd56fbf /tests/helpers/run_cocoa_bundle.py
parent08dc9047098d6d96791024ac7d8f5837633673ef (diff)
better public interface and doxygen
Diffstat (limited to 'tests/helpers/run_cocoa_bundle.py')
-rw-r--r--tests/helpers/run_cocoa_bundle.py68
1 files changed, 68 insertions, 0 deletions
diff --git a/tests/helpers/run_cocoa_bundle.py b/tests/helpers/run_cocoa_bundle.py
new file mode 100644
index 0000000..338f38e
--- /dev/null
+++ b/tests/helpers/run_cocoa_bundle.py
@@ -0,0 +1,68 @@
+#!/usr/bin/env python3
+"""Run a packaged Cocoa suite, preserving output and a machine-readable report."""
+
+import argparse
+import hashlib
+import json
+import os
+from pathlib import Path
+import platform
+import re
+import subprocess
+import sys
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('--list', action='store_true', help='List tests without executing them.')
+ args = parser.parse_args()
+ root = Path(__file__).resolve().parent
+ manifest = json.loads((root / 'manifest.json').read_text())
+ if args.list:
+ print('Architecture:', manifest['architecture'])
+ for test in manifest['tests']:
+ print(test['name'])
+ return
+ if sys.platform != 'darwin':
+ parser.error('Run this suite in a macOS desktop session.')
+ if int(platform.mac_ver()[0].split('.')[0]) < manifest['minimum_macos']:
+ parser.error('This suite requires macOS 14 or newer.')
+ architecture = {'arm64': 'aarch64'}.get(platform.machine(), platform.machine())
+ if architecture != manifest['architecture']:
+ parser.error('Use the bundle matching this Python process architecture.')
+ for relative, expected in manifest['sha256'].items():
+ if hashlib.sha256((root / relative).read_bytes()).hexdigest() != expected:
+ parser.error('Bundle file changed: ' + relative)
+
+ logs = root / 'logs'
+ logs.mkdir(exist_ok=True)
+ env = os.environ.copy()
+ env['DYLD_LIBRARY_PATH'] = str(root)
+ results = []
+ for test in manifest['tests']:
+ name = test['name']
+ log = logs / (re.sub(r'[^A-Za-z0-9_-]', '_', name) + '.log')
+ command = [str(root / test['cmd'][0]), *test['cmd'][1:]]
+ with log.open('w') as output:
+ try:
+ process = subprocess.run(command, cwd=root, env=env, stdout=output,
+ stderr=subprocess.STDOUT, timeout=test['timeout'] or None)
+ result = {'name': name, 'returncode': process.returncode,
+ 'status': 'pass' if process.returncode == 0 else 'fail'}
+ except subprocess.TimeoutExpired:
+ output.write('\nTest timed out.\n')
+ result = {'name': name, 'status': 'timeout'}
+ except OSError as error:
+ output.write(str(error) + '\n')
+ result = {'name': name, 'status': 'error'}
+ results.append(result)
+ print(f'{name}: {result["status"]}', flush=True)
+ report = root / 'results.json'
+ report.write_text(json.dumps(results, indent=2) + '\n')
+ failed = sum(result['status'] != 'pass' for result in results)
+ print(f'{len(results) - failed} passed, {failed} failed. Logs: {logs}')
+ sys.exit(1 if failed else 0)
+
+
+if __name__ == '__main__':
+ main()