from pathlib import Path import importlib.util,json,tempfile from policy_harness import ROOT,body,run spec=importlib.util.spec_from_file_location('import_settings',ROOT/'tools/import_settings.py') m=importlib.util.module_from_spec(spec);spec.loader.exec_module(m) result,deferred=m.merge({'configVersion':1,'reportIntervalSeconds':20.0,'supportSquadLimit':2,'responseRadiusMetres':1500,'convoyCount':3},{'aiIntelChancePercent':0,'intelRevealChancePercent':100}) assert result==dict(reportIntervalSeconds=20,supportSquadLimit=2,responseRadiusMetres=1500,aiIntelChancePercent=0,intelRevealChancePercent=100,radioDefenceSeconds=180,startTimeMinutes=840,timeMultiplier=1,startDateCode=0,weatherProfile=0,stingerChanceOneIn=15) assert deferred==['ai:convoyCount'] assert m.merge(ai={'stingerChanceOneIn':37})[0]['stingerChanceOneIn']==37 assert m.merge(ai={'stingerChanceOneIn':0})[0]['stingerChanceOneIn']==0 assert m.merge()[0]=={k:v[0] for k,v in m.SCHEMA.items()} for key,(_,lo,hi) in m.SCHEMA.items(): if key not in m.AI_KEYS and key not in m.INTEL_KEYS:continue for invalid in (lo-1,hi+1,True,False,None,'10',lo+0.5,float('nan'),float('inf')): try:m.merge(**({'ai':{key:invalid}} if key in m.AI_KEYS else {'intel':{key:invalid}})) except ValueError:pass else:raise AssertionError((key,invalid)) with tempfile.TemporaryDirectory() as tmp: dest=Path(tmp)/'rereintroduced.json' m.write_new(dest,json.dumps(result));before=dest.read_bytes() try:m.write_new(dest,'overwrite') except FileExistsError:pass else:raise AssertionError('Existing destination overwritten') assert dest.read_bytes()==before assert sorted(p.name for p in Path(tmp).iterdir())==['rereintroduced.json'] # Test the actual runtime validator against the migration schema at each boundary. validator=body(ROOT/'addons/core/Scripts/Game/ERR/ERR_Settings.c','static bool Valid(').replace('string key','std::string key') checks=[] for key,(_,lo,hi) in m.SCHEMA.items(): for value,expected in [(lo-1,False),(lo,True),(hi,True),(hi+1,False)]: checks.append(f'assert(Valid("{key}",{value})=={str(expected).lower()});') run('#include \n#include \n'+validator+'\nint main(){'+''.join(checks)+'assert(!Valid("unknown",1));}\n') print('PASS: legacy values preserved, unsupported fields reported, invalid data rejected, existing files protected, runtime bounds aligned')