245 lines
12 KiB
Python
245 lines
12 KiB
Python
"""Bounded a95db10 tests against the stamped 7e25b3d core; no Cargo or cache writes.
|
|
|
|
After the coordinator grants a compiler lease:
|
|
python .local/standalone-port-falsifiers.py build UNIQUE-LABEL
|
|
python .local/standalone-port-falsifiers.py run UNIQUE-LABEL
|
|
Expected test failures are preserved as failures, never translated to passes.
|
|
"""
|
|
from datetime import datetime, timezone
|
|
from pathlib import Path
|
|
import hashlib
|
|
import json
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
import time
|
|
|
|
ROOT = Path(__file__).resolve().parent.parent
|
|
BASE = ROOT / '.local/resize-port-policy-20260912'
|
|
WORK = ROOT / '.local/resize-port-falsifiers-20260912'
|
|
CORE_SOURCE = '7e25b3d3907693cbbf03bb51b5e08b01d743a934'
|
|
TEST_SOURCE = 'a95db10ce73d639f59eb1ec1153de26f4967881c'
|
|
TEST_PATH = 'crates/oa-core/tests/experimental_port_policy_falsifiers.rs'
|
|
TEST_SHA = '0a659fad3e5afcf563bacb2f10467bb2428c385ce991c1e7eb8c04207efb3255'
|
|
GATE = BASE / '.local/gate-7e25b3d-20260912-01'
|
|
TARGET = BASE / '.local/target-7e25b3d-01'
|
|
DEPS = TARGET / 'debug/deps'
|
|
FINGERPRINTS = TARGET / 'debug/.fingerprint'
|
|
TESTS = [
|
|
'a_point_one_height_increase_does_not_needlessly_flip_twelve_of_twenty_ports',
|
|
'capacity_spillover_does_not_add_a_blocked_mandatory_stub_above_the_owner',
|
|
]
|
|
|
|
|
|
def utc():
|
|
return datetime.now(timezone.utc).isoformat()
|
|
|
|
|
|
def sha(path):
|
|
return hashlib.sha256(path.read_bytes()).hexdigest()
|
|
|
|
|
|
def read(path):
|
|
return json.loads(path.read_text(encoding='utf-8-sig'))
|
|
|
|
|
|
def write(path, value):
|
|
with path.open('x', encoding='utf-8', newline='\n') as stream:
|
|
stream.write(json.dumps(value, indent=2) + '\n')
|
|
|
|
|
|
def git(where, *args):
|
|
return subprocess.check_output(['git', *args], cwd=where).decode().strip()
|
|
|
|
|
|
def stamp(paths):
|
|
return {str(path): {'sha256': sha(path), 'bytes': path.stat().st_size}
|
|
for path in sorted(set(paths))}
|
|
|
|
|
|
def changed(files):
|
|
return [name for name, record in files.items()
|
|
if not Path(name).is_file() or sha(Path(name)) != record['sha256']]
|
|
|
|
|
|
def invoke(command, log, env=None):
|
|
started, clock = utc(), time.monotonic()
|
|
print('START', command, flush=True)
|
|
with log.open('xb') as stream:
|
|
result = subprocess.run(command, cwd=WORK, env=env,
|
|
stdout=stream, stderr=subprocess.STDOUT)
|
|
return {'command': command, 'start': started, 'end': utc(),
|
|
'seconds': round(time.monotonic() - clock, 3),
|
|
'exit': result.returncode, 'log': str(log), 'log_sha256': sha(log)}
|
|
|
|
|
|
def build(out):
|
|
# These are source/receipt checks only. No Cargo metadata/build is invoked.
|
|
manifest = read(GATE / 'inputs.json')
|
|
comparison = read(GATE / 'comparison.json')
|
|
allocator = read(GATE / 'allocator-corrected.json')
|
|
anchors = read(GATE / 'port-anchors.json')
|
|
assert manifest['source'] == CORE_SOURCE
|
|
for record, stem in [(comparison, 'comparison'), (allocator, 'allocator-corrected'),
|
|
(anchors, 'port-anchors')]:
|
|
assert record['source'] == CORE_SOURCE and record['exit'] == 0
|
|
assert not record['changed_inputs'] and not record['changed_protected']
|
|
assert sha(GATE / (stem + '.log')) == record['log_sha256']
|
|
assert allocator['accepted'] and allocator['passed_tests'] == 3
|
|
for where, source in [(BASE, CORE_SOURCE), (WORK, TEST_SOURCE)]:
|
|
assert git(where, 'rev-parse', 'HEAD') == source
|
|
assert not git(where, 'status', '--porcelain', '--untracked-files=no')
|
|
for name, digest in manifest['inputs'].items():
|
|
assert sha(where / name) == digest, (where, name)
|
|
assert git(WORK, 'diff', '--name-only', CORE_SOURCE, TEST_SOURCE) == TEST_PATH
|
|
test = WORK / TEST_PATH
|
|
assert sha(test) == TEST_SHA
|
|
committed = subprocess.check_output(['git', 'show', TEST_SOURCE + ':' + TEST_PATH], cwd=WORK)
|
|
assert hashlib.sha256(committed).hexdigest() == TEST_SHA
|
|
|
|
# Derive the anchor from the recorded passing executable, then select rlibs
|
|
# by the dependency fingerprints embedded in that executable's Cargo record.
|
|
executable = next(a for a in comparison['artifacts']
|
|
if Path(a['path']).name.startswith('experimental_port_policy-'))
|
|
anchor_exe = BASE / executable['path']
|
|
assert sha(anchor_exe) == executable['sha256']
|
|
suffix = anchor_exe.stem.rsplit('-', 1)[1]
|
|
anchor = FINGERPRINTS / ('oa-core-' + suffix) / 'test-integration-test-experimental_port_policy.json'
|
|
meta = read(anchor)
|
|
dependencies, fingerprint_files = {}, [anchor]
|
|
for _, name, _, expected in meta['deps']:
|
|
if name not in ['oa_core', 'serde_json']:
|
|
continue
|
|
matches = []
|
|
for fingerprint in FINGERPRINTS.glob('*/lib-' + name):
|
|
if int.from_bytes(bytes.fromhex(fingerprint.read_text().strip()), 'little') != expected:
|
|
continue
|
|
crate_suffix = fingerprint.parent.name.rsplit('-', 1)[1]
|
|
rlib = DEPS / ('lib' + name + '-' + crate_suffix + '.rlib')
|
|
if rlib.is_file():
|
|
matches.append((rlib, fingerprint, fingerprint.with_suffix('.json')))
|
|
assert len(matches) == 1, (name, matches)
|
|
dependencies[name] = matches[0][0]
|
|
fingerprint_files.extend(matches[0][1:])
|
|
assert set(dependencies) == {'oa_core', 'serde_json'}
|
|
core_artifact = next(a for a in comparison['artifacts']
|
|
if (BASE / a['path']).resolve() == dependencies['oa_core'].resolve())
|
|
assert sha(dependencies['oa_core']) == core_artifact['sha256']
|
|
core_meta = read(next(p for p in fingerprint_files if p.name == 'lib-oa_core.json'))
|
|
assert next(d[3] for d in core_meta['deps'] if d[1] == 'serde_json') == next(
|
|
d[3] for d in meta['deps'] if d[1] == 'serde_json')
|
|
|
|
tools = manifest['toolchain']['paths']
|
|
for name in ['rustc', 'linker']:
|
|
assert sha(Path(tools[name]['path'])) == tools[name]['sha256']
|
|
rustc, linker = tools['rustc']['path'], tools['linker']['path']
|
|
version = subprocess.check_output([rustc, '-Vv'], cwd=WORK).decode().strip()
|
|
assert version == manifest['toolchain']['rustc']
|
|
environment_file = ROOT / '.local/toolchain/env.ps1'
|
|
assert sha(environment_file) == manifest['protected'][str(environment_file)]
|
|
for key in ['CARGO_HOME', 'RUSTUP_HOME']:
|
|
assert os.environ.get(key) == manifest['environment'][key], key
|
|
|
|
# Stamp every possible external linker input in this one frozen dependency
|
|
# directory. This records transitive inputs without copying/linking caches.
|
|
artifacts = [p for p in DEPS.iterdir() if p.is_file() and p.suffix in
|
|
['.rlib', '.rmeta', '.dll', '.lib', '.a']]
|
|
files = [WORK / name for name in manifest['inputs']]
|
|
files += [BASE / name for name in manifest['inputs']]
|
|
files += [test, Path(__file__).resolve(), environment_file, anchor_exe]
|
|
files += [GATE / name for name in ['inputs.json', 'comparison.json', 'comparison.log',
|
|
'allocator-corrected.json', 'allocator-corrected.log', 'port-anchors.json', 'port-anchors.log']]
|
|
files += fingerprint_files + artifacts + [Path(tools[n]['path']) for n in ['rustc', 'linker']]
|
|
# Root desktop artifacts are not inputs to this build. If present, monitor
|
|
# the old protected rlib's current bytes rather than assuming root stayed at
|
|
# its earlier commit while integration proceeded.
|
|
protected = ROOT / 'target/debug/deps/liboa_core-145180297aa692e4.rlib'
|
|
if protected.is_file():
|
|
files.append(protected)
|
|
inputs = stamp(files)
|
|
binary = out / 'port-policy-falsifiers.exe'
|
|
command = [rustc, '--edition=2024', '--test', '-D', 'warnings', '-C', 'linker=' + linker,
|
|
'-L', 'dependency=' + str(DEPS)]
|
|
for name, rlib in dependencies.items():
|
|
command += ['--extern', name + '=' + str(rlib)]
|
|
command += [str(test), '-o', str(binary)]
|
|
write(out / 'inputs.json', {'core_source': CORE_SOURCE, 'test_source': TEST_SOURCE,
|
|
'toolchain': manifest['toolchain'], 'dependencies': {k: str(v) for k, v in dependencies.items()},
|
|
'scope': 'Exact committed standalone integration-test bytes; reused matching 7e25 core. No Cargo/root targets.',
|
|
'files': inputs, 'command': command})
|
|
result = invoke(command, out / 'build.log')
|
|
result.update({'core_source': CORE_SOURCE, 'test_source': TEST_SOURCE,
|
|
'changed_inputs': changed(inputs),
|
|
'binary': stamp([binary]) if binary.is_file() else {}})
|
|
result['build_accepted'] = result['exit'] == 0 and not result['changed_inputs']
|
|
write(out / 'build.json', result)
|
|
print(json.dumps(result), flush=True)
|
|
return 0 if result['build_accepted'] else 1
|
|
|
|
|
|
def run(out):
|
|
build_record = read(out / 'build.json')
|
|
inputs = read(out / 'inputs.json')['files']
|
|
assert build_record['build_accepted']
|
|
assert not changed(inputs) and not changed(build_record['binary'])
|
|
assert git(WORK, 'rev-parse', 'HEAD') == TEST_SOURCE
|
|
assert git(BASE, 'rev-parse', 'HEAD') == CORE_SOURCE
|
|
binary = next(iter(build_record['binary']))
|
|
selected = invoke([binary, '--list', '--format', 'terse'], out / 'list.log')
|
|
names = [line.removesuffix(': test') for line in (out / 'list.log').read_text().splitlines()
|
|
if line.endswith(': test')]
|
|
selected['selected_tests'] = names
|
|
write(out / 'list.json', selected)
|
|
assert selected['exit'] == 0 and sorted(names) == sorted(TESTS), names
|
|
results = []
|
|
for i, test_name in enumerate(TESTS, 1):
|
|
env = os.environ.copy()
|
|
geometry = out / ('case-' + str(i) + '-geometry')
|
|
assert not geometry.exists()
|
|
env['OA_PORT_POLICY_RECEIPTS'] = str(geometry)
|
|
result = invoke([binary, test_name, '--exact', '--nocapture', '--test-threads=1'],
|
|
out / ('case-' + str(i) + '.log'), env)
|
|
log = Path(result['log']).read_text(encoding='utf-8', errors='replace')
|
|
marker = ('Prospective resize-stability criterion failed:' if i == 1
|
|
else 'Prospective exit-clearance criterion failed:')
|
|
result.update({'test': test_name, 'expected_exit': 101,
|
|
'expected_acceptance_failure_observed': result['exit'] == 101 and marker in log,
|
|
'test_passed': result['exit'] == 0,
|
|
'changed_inputs': changed(inputs),
|
|
'changed_binary': changed(build_record['binary']),
|
|
'geometry': stamp(p for p in geometry.rglob('*') if p.is_file())
|
|
if geometry.exists() else {}})
|
|
write(out / ('case-' + str(i) + '.json'), result)
|
|
results.append(result)
|
|
print(json.dumps({k: v for k, v in result.items() if k != 'geometry'}), flush=True)
|
|
# A prospective criterion failure must not skip the other falsifier.
|
|
if result['changed_inputs'] or result['changed_binary']:
|
|
break
|
|
summary = {'core_source': CORE_SOURCE, 'test_source': TEST_SOURCE, 'results': results,
|
|
'tests_passed': sum(r['test_passed'] for r in results),
|
|
'expected_failures_observed': sum(r['expected_acceptance_failure_observed'] for r in results),
|
|
'policy_accepted': False}
|
|
write(out / 'run.json', summary)
|
|
print(json.dumps({k: v for k, v in summary.items() if k != 'results'}), flush=True)
|
|
# Preserve failing process semantics even if both predictions are confirmed.
|
|
if len(results) != 2 or any(r['changed_inputs'] or r['changed_binary'] for r in results):
|
|
return 1
|
|
return 101 if any(r['exit'] != 0 for r in results) else 0
|
|
|
|
|
|
if __name__ == '__main__':
|
|
mode, label = sys.argv[1:]
|
|
assert mode in ['build', 'run'] and label.replace('-', '').isalnum()
|
|
output = ROOT / '.local/native-qa' / label
|
|
if mode == 'build':
|
|
output.mkdir(exist_ok=False)
|
|
else:
|
|
assert output.is_dir() and not (output / 'run.json').exists()
|
|
try:
|
|
code = build(output) if mode == 'build' else run(output)
|
|
except Exception as error:
|
|
write(output / (mode + '-exception.json'), {'utc': utc(), 'type': type(error).__name__,
|
|
'error': str(error), 'core_source': CORE_SOURCE, 'test_source': TEST_SOURCE})
|
|
raise
|
|
raise SystemExit(code)
|