338 lines
24 KiB
Python
338 lines
24 KiB
Python
"""Read-only portable verification of recorded e34 gates; never execute archived code."""
|
|
from pathlib import Path, PurePosixPath
|
|
import argparse
|
|
import hashlib
|
|
import json
|
|
import ntpath
|
|
import re
|
|
import subprocess
|
|
import zipfile
|
|
|
|
SOURCE = 'e34ba27e26ede3ab55f276acc250d92b2e0c3204'
|
|
TREE = '29f769926e2e907f0b40c3b33ec36658ee6601b7'
|
|
FB = 'fb978bc1716f77bb200b6822ccbc15fe3eb3553f7066fb8fca780fe651ffd51a'
|
|
DIRECT = 'de031fc497ba71e4de9602921b1208a2e8c672abefb9a95d7f421e6258411d04'
|
|
NATIVE = 'c1b736290bae198fb8230011d9848c0679483e5f5fbf46343c89ad66da059932'
|
|
SUPPLEMENT = '9765c43e2e6d826c86dfcf82042ba6dc5ca035ab55ef010eb1cdfe27162b9a8e'
|
|
TRANSITION = 'dde99bfc6108862d8ad545e0a42290987ab44f2007c71e99f407ab640f8fe42e'
|
|
LIST = 'combined-workspace-list-e34-1'
|
|
FULL = 'combined-workspace-full-e34-1'
|
|
REBUILT = {
|
|
'arcadia-dc4fafbbc0215f88.exe': ('oa-cli', '2bee6abfeed32a2cd2a3ef958dd95b17f75dec4189199f43403de08c11aabf25'),
|
|
'source_cli-628cfee23782acb5.exe': ('oa-cli', 'a40ae4b7af2ff749d5c206bc15be4b74c89e635c2e6f8c3c610f0b692147f573'),
|
|
'arcadia_studio-c5b42126ba36cd38.exe': ('oa-desktop', '4ee353b9bf1940258a27fad41b904b2638783c1a8c7f9498c118c5ba62df71e9'),
|
|
}
|
|
HISTORICAL_LOG_SHA256 = '2a043b7f8dd2ba952f0a2f967a10936d0dc805913d8743375a714c4bde4a0c2e'
|
|
HISTORICAL_FAILED = {
|
|
'app::behavior_removal_tests::mounted_scenario_use_delete_keeps_definition_and_second_use_and_rejects_owner_replay',
|
|
'behavior::scenario::workspace::details_tests::details_opens_current_saved_view_properties_after_following_diagram_picker',
|
|
'behavior::scenario::workspace::details_tests::saved_details_opens_real_editable_inspector_and_returns_to_same_view',
|
|
}
|
|
# Review policy is independent of the manifest and mutable receipt summaries.
|
|
# Basenames identify sections within the already checked literal workspace inventory.
|
|
EXPECTED_IGNORED = (
|
|
('r6_data-f7978707542e0007.exe', 'inheritance_chain_validation_scaling_probe',
|
|
'explicit inheritance scaling probe; run with --ignored --nocapture'),
|
|
('arcadia_studio-c5b42126ba36cd38.exe', 'app::source_rename::timing_tests::accepted_release1_prepare_commit_sync_and_confirm_timing',
|
|
'manual Windows dev/debug rename latency trial; run alone with --ignored --nocapture --test-threads=1'),
|
|
('arcadia_studio-c5b42126ba36cd38.exe', 'app::source_rename::timing_tests::layout_timing_tests::accepted_release1_constructor_vs_reuse_through_next_highlight',
|
|
'manual Windows dev/debug editor replacement + layout/highlight trial; run alone with --ignored --nocapture --test-threads=1'),
|
|
('arcadia_studio-c5b42126ba36cd38.exe', 'app::source_symbols::tests::source_symbols_100_modules_1000_definitions_10000_uses',
|
|
'manual 100-module latency/process-memory trial; run alone with --ignored --nocapture --test-threads=1'),
|
|
('arcadia_studio-c5b42126ba36cd38.exe', 'behavior::scenario::spacing::controller::timing_tests::saved_spacing_capture_prepare_20_lanes_1000_messages_3_views',
|
|
'Diagnostic timing only; run alone with --exact --ignored --nocapture after correctness gates; no latency acceptance threshold'),
|
|
('arcadia_studio-c5b42126ba36cd38.exe', 'source_annotations::anchor_tests::final_multi_glyph_cluster_anchor_uses_logical_trailing_advance_edge',
|
|
'manual supported-font cluster and bidi witnesses'),
|
|
('arcadia_studio-c5b42126ba36cd38.exe', 'source_annotations::anchor_tests::mixed_direction_omitted_separator_has_one_logical_predecessor_anchor',
|
|
'manual supported-font cluster and bidi witnesses'),
|
|
('arcadia_studio-c5b42126ba36cd38.exe', 'source_annotations::performance_tests::annotation_projection_cost_distributions',
|
|
'manual diagnostic projection distributions; no fixed machine threshold'),
|
|
)
|
|
PREFIXES = ('Cargo.toml', 'Cargo.lock', 'rust-toolchain.toml', '.cargo', 'build', 'crates',
|
|
'assets', 'docs', 'examples', 'harness/fixtures', 'scripts', 'vendor',
|
|
'harness/experiments/edge-attachments-20260922/native-fixture.arcadia',
|
|
'harness/experiments/textual-authoring-20260911/alarm-response.arcadia')
|
|
|
|
def sha(raw):
|
|
return hashlib.sha256(raw).hexdigest()
|
|
|
|
def pin(raw):
|
|
return {'bytes': len(raw), 'sha256': sha(raw)}
|
|
|
|
def norm(path):
|
|
return path if path.startswith('doctest:') else ntpath.normpath(path)
|
|
|
|
def parse(text):
|
|
return {'listing_members': re.findall(r'^([^\r\n]+): test\r?$', text, re.M),
|
|
'outcomes': [list(t) for t in re.findall(r'^test ([^\r\n]+) \.\.\. (ok|FAILED|ignored)(?:, ([^\r\n]*))?\r?$', text, re.M)],
|
|
'summaries': [list(t) for t in re.findall(r'^test result: (ok|FAILED)\. (\d+) passed; (\d+) failed; (\d+) ignored; (\d+) measured; (\d+) filtered out;', text, re.M)],
|
|
'listing_totals': [list(t) for t in re.findall(r'^(\d+) tests?, (\d+) benchmarks?\r?$', text, re.M)],
|
|
'text_sha256': sha(text.encode())}
|
|
|
|
def sections(text):
|
|
headers = list(re.finditer(r'^\s+(?:Running (?P<kind>[^\r\n]+) \((?P<exe>[^\r\n]+\.exe)\)|Doc-tests (?P<doc>[^\r\n]+))\r?$', text, re.M))
|
|
result = []
|
|
for index, match in enumerate(headers):
|
|
body = text[match.end():headers[index + 1].start() if index + 1 < len(headers) else len(text)]
|
|
result.append({'key': norm(match['exe']) if match['exe'] else 'doctest:' + match['doc'],
|
|
'kind': match['kind'] or 'doctest', **parse(body)})
|
|
assert len(result) == len({s['key'] for s in result})
|
|
return result
|
|
|
|
def outcomes(parsed, names, counts, filtered=0):
|
|
observed = parsed['outcomes']
|
|
assert len(names) == len(set(names))
|
|
assert len(observed) == len({n for n, _, _ in observed}) == len(names)
|
|
assert {n for n, _, _ in observed} == set(names)
|
|
actual = [sum(status == wanted for _, status, _ in observed) for wanted in ('ok', 'FAILED', 'ignored')]
|
|
assert actual == counts
|
|
assert parsed['summaries'] == [['FAILED' if counts[1] else 'ok', *map(str, counts), '0', str(filtered)]]
|
|
return [{'name': n, 'reason': reason} for n, status, reason in observed if status == 'ignored']
|
|
|
|
def verify(folder, repo):
|
|
manifest = json.loads((folder / 'manifest.json').read_bytes())
|
|
assert manifest['source'] == SOURCE and manifest['tree'] == TREE
|
|
assert pin((folder / 'verify.py').read_bytes()) == manifest['verifier']
|
|
assert pin((folder / 'evidence.zip').read_bytes()) == manifest['archive']
|
|
with zipfile.ZipFile(folder / 'evidence.zip') as archive:
|
|
names = archive.namelist()
|
|
assert len(names) == len(set(names)) and set(names) == set(manifest['payloads'])
|
|
assert all(not PurePosixPath(n).is_absolute() and '..' not in PurePosixPath(n).parts and '\\' not in n for n in names)
|
|
assert all(not n.lower().endswith(('.exe', '.dll', '.pdb')) for n in names)
|
|
data = {n: archive.read(n) for n in names}
|
|
for name, raw in data.items():
|
|
assert pin(raw) == manifest['payloads'][name], name
|
|
read = lambda name: json.loads(data[name])
|
|
source_inputs = {}
|
|
|
|
def input_set(raw, source):
|
|
record = json.loads(raw)
|
|
assert record['source'] == source and len(record['inputs']) == 760
|
|
assert len(record['inputs']) == len({i['path'] for i in record['inputs']})
|
|
for item in record['inputs']:
|
|
key = (source, item['path'])
|
|
assert key not in source_inputs or source_inputs[key] == item
|
|
source_inputs[key] = item
|
|
return record
|
|
|
|
def gate(name, launcher, source=SOURCE, exit_code=0):
|
|
r = read('gates/' + name + '.result.json')
|
|
raw = data['gates/' + name + '.log']
|
|
inputs = data['gates/' + r['inputs']]
|
|
assert r['source'] == r['head_after'] == source and r['exit'] == exit_code
|
|
assert not r['changed_inputs'] and sha(raw) == r['log_sha256']
|
|
assert sha(inputs) == r['inputs_sha256']
|
|
assert r['launcher_sha256'] == r['launcher_sha256_after'] == launcher
|
|
assert sha(data['launchers/' + launcher + '.py']) == launcher
|
|
input_set(inputs, source)
|
|
return r, raw.decode(), inputs
|
|
|
|
listing, list_text, input_raw = gate(LIST, FB)
|
|
full, full_text, full_inputs = gate(FULL, FB)
|
|
base_command = ['cargo', 'test', '--locked', '--offline', '--workspace', '--no-fail-fast', '--']
|
|
assert listing['command'] == base_command + ['--list'] and listing['mode'] == 'list'
|
|
assert full['command'] == base_command + ['--test-threads=1'] and full['mode'] == 'test'
|
|
assert listing['scope'] == full['scope'] == 'workspace' and not listing['filter'] and not full['filter']
|
|
assert full_inputs == input_raw
|
|
listed_sections, full_sections = sections(list_text), sections(full_text)
|
|
for actual, recorded in ((listed_sections, listing['workspace_sections']), (full_sections, full['workspace_sections'])):
|
|
assert actual == [{**s, 'key': norm(s['key'])} for s in recorded]
|
|
assert len(listed_sections) == len(full_sections) == 63
|
|
listed = {s['key']: s for s in listed_sections}
|
|
executed = {s['key']: s for s in full_sections}
|
|
assert listed.keys() == executed.keys()
|
|
assert sum(len(s['listing_members']) for s in listed_sections) == listing['listing_count'] == 2013
|
|
assert re.findall(r'^([^\r\n]+): test\r?$', list_text, re.M) == listing['listing_members']
|
|
old_artifacts = {norm(a['path']): a for a in listing['artifacts']}
|
|
assert len(old_artifacts) == len(listing['artifacts']) == 60
|
|
assert set(old_artifacts) == {k for k in listed if not k.startswith('doctest:')}
|
|
|
|
supplement_root = 'supplement/combined-rebuilt-inventory-e34-2/'
|
|
supplement = read(supplement_root + 'result.json')
|
|
assert supplement['source'] == SOURCE and supplement['baseline'] == LIST
|
|
assert supplement['baseline_sha256'] == sha(data['gates/' + LIST + '.result.json'])
|
|
assert supplement['launcher_sha256'] == supplement['launcher_sha256_after'] == sha(data[supplement_root + 'launcher.py']) == SUPPLEMENT
|
|
assert data[supplement_root + supplement['inputs']] == input_raw and supplement['inputs_sha256'] == sha(input_raw)
|
|
assert supplement['binding_unchanged'] and supplement['before'] == supplement['after']
|
|
before = supplement['before']
|
|
assert before == read(supplement_root + 'before.json')
|
|
assert before['head'] == SOURCE and not before['tracked_status'] and not before['changed_inputs']
|
|
assert before['baseline_sha256'] == supplement['baseline_sha256'] and before['inputs_sha256'] == sha(input_raw)
|
|
assert before['environment']['ARCADIA_CODEC_LIFECYCLE_PHASE'] is None and before['environment']['RUST_MIN_STACK'] is None
|
|
replacements = {}
|
|
assert len(supplement['inventories']) == 3
|
|
for item in supplement['inventories']:
|
|
key = norm(item['path'])
|
|
assert item == read(supplement_root + ntpath.splitext(ntpath.basename(key))[0] + '.result.json')
|
|
package, expected_hash = REBUILT[ntpath.basename(key)]
|
|
assert item['exit'] == 0 and item['command'] == [item['path'], '--list']
|
|
assert norm(item['cwd']).endswith('\\crates\\' + package)
|
|
assert item['artifact_before'] == item['artifact_after'] and item['artifact_before']['sha256'] == expected_hash
|
|
assert item['baseline_artifact'] == old_artifacts[key]
|
|
raw = data[supplement_root + item['log']]
|
|
assert sha(raw) == item['log_sha256']
|
|
parsed = parse(raw.decode())
|
|
assert parsed['listing_members'] == item['listing_members'] == listed[key]['listing_members']
|
|
assert parsed['listing_totals'] == item['listing_totals'] == [[str(len(item['listing_members'])), '0']]
|
|
assert item['matches_baseline_names']
|
|
replacements[key] = {'path': item['path'], **item['artifact_before']}
|
|
assert {ntpath.basename(k) for k in replacements} == set(REBUILT)
|
|
expected_artifacts = [replacements.get(norm(a['path']), a) for a in listing['artifacts']]
|
|
assert full['artifacts'] == expected_artifacts
|
|
ignored = []
|
|
passed = 0
|
|
for key, section in listed.items():
|
|
names = section['listing_members']
|
|
assert section['listing_totals'] == [[str(len(names)), '0']]
|
|
counts = [sum(status == wanted for _, status, _ in executed[key]['outcomes']) for wanted in ('ok', 'FAILED', 'ignored')]
|
|
assert counts[1] == 0
|
|
ignored += [{'section': key, **i} for i in outcomes(executed[key], names, counts)]
|
|
passed += counts[0]
|
|
assert passed == 2005 and len(ignored) == 8
|
|
assert ignored == manifest['ignored']
|
|
assert tuple((ntpath.basename(i['section']), i['name'], i['reason']) for i in ignored) == EXPECTED_IGNORED
|
|
|
|
desktop = next(a for a in listing['artifacts'] if ntpath.basename(a['path']).startswith('arcadia_studio-'))
|
|
desktop_names = listed[norm(desktop['path'])]['listing_members']
|
|
for name, selector, count in (
|
|
('combined-details-e34-direct-1', 'workspace::details_tests', 6),
|
|
('combined-removal-e34-direct-1', 'mounted_scenario_use_delete_keeps_definition_and_second_use_and_rejects_owner_replay', 1)):
|
|
r, text, raw = gate(name, DIRECT)
|
|
assert raw == input_raw and r['execution'] == 'direct-listed-executable'
|
|
assert r['command'] == [desktop['path'], selector, '--test-threads=1']
|
|
assert r['filter'] == selector and r['listing'] == LIST and r['artifacts'] == [desktop]
|
|
assert r['head_before'] == SOURCE and not r['tracked_status_before'] and not r['tracked_status_after']
|
|
assert r['binding_unchanged'] and r['outcome_membership_exact']
|
|
assert r['artifact_before'] == r['artifact_after'] == {k: desktop[k] for k in ('bytes', 'sha256')}
|
|
assert r['environment'] == r['environment_after']
|
|
assert r['environment']['ARCADIA_CODEC_LIFECYCLE_PHASE'] is None and r['environment']['RUST_MIN_STACK'] is None
|
|
assert r['listing_before'] == r['listing_after']
|
|
for path, expected in r['listing_before'].items():
|
|
prefix = 'launchers/' if ntpath.basename(path) == FB + '.py' else 'gates/'
|
|
assert pin(data[prefix + ntpath.basename(path)]) == expected
|
|
selected = sorted(n for n in desktop_names if selector in n)
|
|
assert r['selected'] == selected and len(selected) == count
|
|
outcomes(parse(text), selected, [count, 0, 0], len(desktop_names) - count)
|
|
|
|
strict, text, raw = gate('combined-strict-e34-1', FB)
|
|
assert raw == input_raw and strict['scope'] == 'workspace' and strict['mode'] == 'clippy'
|
|
assert strict['command'] == ['cargo', 'clippy', '--locked', '--offline', '--workspace', '--all-targets', '--', '-D', 'warnings']
|
|
assert 'Finished `dev` profile' in text and not re.search(r'^error(?:\[|:)', text, re.M)
|
|
native, text, raw = gate('combined-native-e34-1', NATIVE)
|
|
assert raw == input_raw and native['scope'] == 'native' and native['mode'] == 'build'
|
|
assert native['command'] == ['cargo', 'build', '--locked', '--offline', '-p', 'oa-desktop', '-p', 'oa-core', '--bin', 'arcadia-studio', '--example', 'attachment_snapshot', '--example', 'state_bend_routing_snapshot']
|
|
assert 'Finished `dev` profile' in text and native['duration_monotonic_ns'] > 0
|
|
assert not re.search(r'^\s*error(?:\[|:)', text, re.M)
|
|
for recorded in (listing, full, strict, native):
|
|
assert recorded['environment']['CARGO_BUILD_JOBS'] == '1'
|
|
assert recorded['environment']['CARGO_INCREMENTAL'] == '0'
|
|
assert norm(recorded['environment']['CARGO_TARGET_DIR']) == 'C:\\Users\\User\\Documents\\Git\\ARCADIA-Studio\\target'
|
|
assert [(ntpath.basename(a['path']), a['bytes'], a['sha256']) for a in native['artifacts']] == [
|
|
('arcadia-studio.exe', 119151616, 'd8f60c910c6316878538689a5ae0cc6aaf173735dcf7f5aeef75026ce86f4931'),
|
|
('attachment_snapshot.exe', 19513344, '60e1f5807f4959676798482c8269fe1023507ad3ac305b5750eab192e1a4d2d4'),
|
|
('state_bend_routing_snapshot.exe', 21684736, 'cb8ac3958b9010c78b8e3d4048424fb0c81fe39fbdeec792f2989f092b2a0d40')]
|
|
|
|
failed_prefix = 'supplement/combined-rebuilt-inventory-e34-1/'
|
|
failure = read(failed_prefix + 'arcadia-dc4fafbbc0215f88.result.json')
|
|
failure_before = read(failed_prefix + 'before.json')
|
|
assert failure_before['head'] == SOURCE and not failure_before['tracked_status'] and not failure_before['changed_inputs']
|
|
assert failure_before['baseline_sha256'] == supplement['baseline_sha256']
|
|
assert data[failed_prefix + 'inputs.json'] == input_raw
|
|
assert failure_before['inputs_sha256'] == sha(input_raw)
|
|
assert failure_before['environment']['ARCADIA_CODEC_LIFECYCLE_PHASE'] is None
|
|
assert failure_before['environment']['RUST_MIN_STACK'] is None
|
|
assert sha(data[failed_prefix + 'launcher.py']) == SUPPLEMENT
|
|
assert failure['exit'] == 3221225781 and failure['command'] == [failure['path'], '--list']
|
|
failure_key = norm(failure['path'])
|
|
assert ntpath.basename(failure_key) == 'arcadia-dc4fafbbc0215f88.exe'
|
|
assert failure['baseline_artifact'] == old_artifacts[failure_key]
|
|
successful_retry = next(i for i in supplement['inventories'] if norm(i['path']) == failure_key)
|
|
assert failure['cwd'] == successful_retry['cwd']
|
|
assert failure['artifact_before'] == successful_retry['artifact_before']
|
|
assert failure['artifact_before'] == failure['artifact_after']
|
|
assert failure['artifact_before']['sha256'] == REBUILT['arcadia-dc4fafbbc0215f88.exe'][1]
|
|
assert data[failed_prefix + failure['log']] == b'' and failure['log_sha256'] == sha(b'')
|
|
|
|
transition = read('transition/result.json')
|
|
assert transition['source'] == transition['head_before'] == transition['head_after'] == SOURCE
|
|
assert transition['exit'] == 0 and transition['admitted_build'] and transition['command_launched']
|
|
assert not transition['changed_inputs'] and not transition['changed_external_inputs'] and not transition['validation_errors']
|
|
assert not transition['tracked_status_before'] and not transition['tracked_status_after']
|
|
assert transition['launcher_sha256'] == transition['launcher_sha256_after'] == sha(data['transition/' + TRANSITION + '.py']) == TRANSITION
|
|
assert transition['environment'] == transition['environment_after']
|
|
assert transition['scope'] == 'external-transition-oracle' and transition['mode'] == 'build'
|
|
assert transition['environment']['CARGO_BUILD_JOBS'] == '1' and transition['environment']['CARGO_INCREMENTAL'] == '0'
|
|
assert transition['command'] == ['cargo', 'build', '--locked', '--offline', '--manifest-path', transition['cwd'] + '\\Cargo.toml', '--bin', 'transition-native-lifecycle', '--message-format=json-render-diagnostics']
|
|
assert data['transition/' + transition['inputs']] == data['transition/' + transition['inputs_after']] == input_raw
|
|
assert transition['inputs_sha256'] == transition['inputs_after_sha256'] == sha(input_raw)
|
|
external = read('transition/' + transition['external_inputs'])
|
|
assert sha(data['transition/' + transition['external_inputs']]) == transition['external_inputs_sha256']
|
|
assert external['inputs'] == transition['external_before'] == transition['external_after']
|
|
assert {i['path'] for i in external['inputs']} == {'Cargo.toml', 'Cargo.lock', 'src/main.rs'}
|
|
preparation = read('transition/prepared/preparation.json')
|
|
assert transition['preparation_before'] == transition['preparation_after'] == external['preparation'] == pin(data['transition/prepared/preparation.json'])
|
|
assert transition['preparation_before']['sha256'] == '6f651b636413e4f6426807ef057cc306a0f4c5b109e9305727c5c7b55c8c9aea'
|
|
for item in external['inputs']:
|
|
assert pin(data['transition/prepared/' + item['path']]) == {k: item[k] for k in ('bytes', 'sha256')} == preparation['files'][item['path']]
|
|
assert sha(data['transition/build.log']) == transition['log_sha256']
|
|
messages = [json.loads(line) for line in data['transition/build.log'].decode().splitlines() if line.startswith('{')]
|
|
assert [m for m in messages if m['reason'] == 'build-finished'] == [{'reason': 'build-finished', 'success': True}]
|
|
artifact_messages = [m for m in messages if m['reason'] == 'compiler-artifact' and m['target']['name'] == 'transition-native-lifecycle' and m.get('executable')]
|
|
assert len(artifact_messages) == len(transition['artifacts']) == 1
|
|
artifact = transition['artifacts'][0]
|
|
message = artifact_messages[0]
|
|
assert message['target']['kind'] == ['bin'] and norm(message['target']['src_path']) == norm(transition['cwd'] + '\\src\\main.rs')
|
|
assert norm(message['executable']) == norm(artifact['cargo_path']) and message['fresh'] == artifact['cargo_fresh']
|
|
assert artifact['sha256'] == 'a7a16bc291e132eaf69e1c42aa45a1440388cdf4bfb1dd4867d76f3ee7146d9a' and artifact['bytes'] == 21854208
|
|
assert {k: transition['binary_after'][k] for k in ('bytes', 'sha256')} == {k: artifact[k] for k in ('bytes', 'sha256')}
|
|
|
|
historical_source = 'f82e29d6b8ed2b5fd23ac806675d3eafe851d104'
|
|
historical_launcher = '0b14e2e80e4c02ecd31f6dfa5fdfaf1594a6bc3ac319530eca1a3c81505a478e'
|
|
old_list, old_text, old_inputs = gate('combined-desktop-list-1', historical_launcher, historical_source)
|
|
old_run, old_run_text, old_run_inputs = gate('combined-desktop-diagnostic-1', historical_launcher, historical_source, 101)
|
|
assert sha(data['gates/combined-desktop-diagnostic-1.log']) == HISTORICAL_LOG_SHA256
|
|
old_command = ['cargo', 'test', '--locked', '--offline', '-p', 'oa-desktop', '--bin', 'arcadia-studio', '--']
|
|
assert old_list['command'] == old_command + ['--list'] and old_run['command'] == old_command + ['--test-threads=1']
|
|
assert old_inputs == old_run_inputs and old_list['artifacts'] == old_run['artifacts']
|
|
historical_names = parse(old_text)['listing_members']
|
|
assert len(historical_names) == 1347
|
|
historical_parsed = parse(old_run_text)
|
|
historical_ignored = outcomes(historical_parsed, historical_names, [1337, 3, 7])
|
|
assert {n for n, status, _ in historical_parsed['outcomes'] if status == 'FAILED'} == HISTORICAL_FAILED
|
|
assert tuple((i['name'], i['reason']) for i in historical_ignored) == tuple((n, reason) for section, n, reason in EXPECTED_IGNORED if section == 'arcadia_studio-c5b42126ba36cd38.exe')
|
|
|
|
def git(*args, input=None):
|
|
return subprocess.run(['git', *args], cwd=repo, input=input, capture_output=True, check=True).stdout
|
|
assert git('rev-parse', SOURCE + '^{tree}').decode().strip() == TREE
|
|
assert git('cat-file', 'commit', SOURCE) == data['source/commit.txt']
|
|
for source in {s for s, _ in source_inputs}:
|
|
expected_paths = sorted(p for s, p in source_inputs if s == source)
|
|
actual_paths = git('ls-tree', '-r', '--name-only', source, *PREFIXES).decode().splitlines()
|
|
assert sorted(actual_paths) == expected_paths and len(expected_paths) == 760
|
|
keys = sorted(source_inputs)
|
|
blobs = git('cat-file', '--batch', input=''.join(f'{s}:{p}\n' for s, p in keys).encode())
|
|
offset = 0
|
|
for key in keys:
|
|
end = blobs.index(b'\n', offset)
|
|
fields = blobs[offset:end].split()
|
|
assert len(fields) == 3 and fields[1] == b'blob'
|
|
size = int(fields[2])
|
|
blob = blobs[end + 1:end + 1 + size]
|
|
assert pin(blob) == {k: source_inputs[key][k] for k in ('bytes', 'sha256')}, key
|
|
offset = end + size + 2
|
|
assert offset == len(blobs)
|
|
return {'status': 'RECORDED_E34_GATES_VERIFIED', 'source': SOURCE, 'tree': TREE,
|
|
'full': {'passed': passed, 'failed': 0, 'ignored': ignored, 'sections': 63, 'executables': 60},
|
|
'focused_passed': 7, 'strict': 'passed', 'recorded_native_builds': 3, 'recorded_external_builds': 1,
|
|
'historical_f82': {'passed': 1337, 'failed': 3, 'ignored': 7},
|
|
'source_blob_checks': len(keys), 'archive_payloads': len(data),
|
|
'limitations': manifest['limitations']}
|
|
|
|
if __name__ == '__main__':
|
|
if not __debug__:
|
|
raise SystemExit('Optimized Python is not supported')
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument('--repo', type=Path, required=True)
|
|
args = parser.parse_args()
|
|
print(json.dumps(verify(Path(__file__).resolve().parent, args.repo), indent=2))
|