Files
EscapistsReintroduced/tools/check.py
T

66 lines
3.8 KiB
Python

#!/usr/bin/env python3
"""Validate addon/resource isolation and execute policy regressions. Not an engine compiler."""
from pathlib import Path
import json,re,subprocess,sys
ROOT=Path(__file__).resolve().parents[1]
BASE='58D0FB3206B6F859'
def check():
ids={};graph={};resources={};paths={};owners={}
for p in sorted((ROOT/'addons').glob('*/addon.gproj')):
text=p.read_text();g=re.search(r'GUID "([A-F0-9]{16})"',text)[1]
assert g not in ids,f'Duplicate addon GUID: {p}'
ids[g]=p.parent.name;graph[g]=re.findall(r'"([A-F0-9]{16})"',text[text.index('Dependencies'):])
assert len(ids)==5,'Expected five addon projects'
def walk(g,stack):
assert g not in stack,'Dependency cycle: '+str(stack+[g])
for dep in graph[g]:
assert dep==BASE or dep in ids,f'External addon dependency {dep}'
if dep!=BASE:walk(dep,stack+[g])
for g in ids:walk(g,[])
for p in (ROOT/'addons').rglob('*.meta'):
m=re.search(r'Name "\{([A-F0-9]{16})\}([^"\n]+)"',p.read_text())
assert m,f'Malformed metadata: {p}'
g,path=m.groups();assert g not in resources,f'Duplicate resource GUID {g}'
addon=p.relative_to(ROOT/'addons').parts[0]
assert p.with_suffix('')==ROOT/'addons'/addon/path, f'Resource path mismatch: {p}'
assert p.with_suffix('').is_file(),f'Missing resource for {p}'
resources[g]=path;paths[path]=g
owners[g]=addon
def visible(g):
result={ids[g]}
for dep in graph[g]:
if dep!=BASE:result.update(visible(dep))
return result
visibility={ids[g]:visible(g) for g in ids}
vanilla=json.loads((ROOT/'docs/vanilla-resources.json').read_text())
for p in (ROOT/'addons').rglob('*'):
if not p.is_file() or p.suffix not in ['.c','.et','.conf','.ent','.layer','.layout','.emat']:continue
s=p.read_text()
assert not re.search(r'\b(?:ESCT\w*|SCRTC_\w+|SCRT_\w+|EAI_\w+)\b',s),f'Original ecosystem dependency: {p}'
for g,path in re.findall(r'\{([A-F0-9]{16})\}([^"\n]+)',s):
assert resources.get(g)==path or vanilla.get(path)==g,f'Unresolved/mismatched resource in {p}: {g} {path}'
if g in owners:
addon=p.relative_to(ROOT/'addons').parts[0]
assert owners[g] in visibility[addon],f'Resource outside declared dependency graph in {p}: {g} {path}'
if p.suffix in ['.et','.conf','.ent','.layout','.emat']:
assert p.with_name(p.name+'.meta').exists(),f'Missing metadata: {p}'
inventory=json.loads((ROOT/'docs/original-resource-inventory.json').read_text())
coverage=json.loads((ROOT/'docs/original-feature-coverage.json').read_text())
mapped=[];feature_ids=set()
for feature in coverage['features']:
assert feature['id'] not in feature_ids,'Duplicate feature responsibility'
feature_ids.add(feature['id'])
assert feature['status'] in {'pending','partial'},'Completion requires a separately reviewed acceptance update'
assert feature['remaining'],'Unfinished responsibilities must describe remaining work'
mapped.extend(feature['original_scripts'])
for path in feature['replacement_files']:
assert (ROOT/path).is_file(),f'Missing replacement reference: {path}'
assert len(mapped)==len(set(mapped)), 'Original scripts assigned more than once'
assert set(mapped)==set(inventory['script_paths']), 'Original inventory has untracked or unknown entries'
print(f'PASS: {len(mapped)} original script entries tracked across {len(feature_ids)} unfinished responsibilities')
print(f'PASS: {len(ids)} isolated addons, acyclic dependencies, {len(resources)} unique resources, exact vanilla references')
for name in ['test_mission_rules.py','test_time_policy.py','test_settings_migration.py','hq_network_regression.py','helicopter_availability_regression.py','mortar_salvo_regression.py']:
subprocess.run([sys.executable,str(ROOT/'tests'/name)],check=True)
print('All repository checks passed. Native compilation and multiplayer tests are separate requirements.')
if __name__=='__main__':check()