Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
49 lines
3.1 KiB
Python
49 lines
3.1 KiB
Python
"""Exercise actual native convoy proof threshold and reject unsafe runner variants."""
|
|
from policy_harness import ROOT, body, run
|
|
import subprocess, sys
|
|
p=ROOT/'addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeConvoyProbe.c'
|
|
s=p.read_text()
|
|
method=body(p,'static bool MovementComplete(').replace('ERR_ForceRules.','ERR_ForceRules::')
|
|
run('''
|
|
#include <cassert>
|
|
#include <cmath>
|
|
struct ERR_ForceRules {static bool Finite(float n){return std::isfinite(n);}};
|
|
'''+method+'''
|
|
int main(){
|
|
assert(MovementComplete(100,20));assert(MovementComplete(200,30));
|
|
assert(!MovementComplete(99.99,20));assert(!MovementComplete(100,19.99));
|
|
assert(!MovementComplete(NAN,20));assert(!MovementComplete(INFINITY,20));
|
|
assert(!MovementComplete(100,NAN));assert(!MovementComplete(100,-20));
|
|
}
|
|
''')
|
|
assert s.startswith('#ifdef WORKBENCH') and 'outcome == "convoy"' in s
|
|
for forbidden in ('SetOrigin(', 'SetAngles(', 'ERR_Actors.Spawn(', 'SpawnCharacterInCompartment(',
|
|
'TrySpawnPrefabToStorage(', 'SetPermanentLOD(', 'ActivateAI(', 'SetCruiseSpeed(',
|
|
'Ready = true', 'ForceUnconsciousness(', 'SetHealth(', 'PrepareConvoy("'):
|
|
assert forbidden not in s, forbidden
|
|
assert 'hq.PrepareConvoy(seed)' in s and 'hq.StartConvoy()' in s
|
|
assert 'seat.GetOccupant() == actor' in s and 'agents.Count() == expected' in s
|
|
assert 'record.Id == m_Task.Receipt.Records[i]' in s
|
|
assert '!operation.Succeeded' in s and 'm_CargoBefore.Contains(item)' in s
|
|
assert 'rifles == 8 && magazines >= 48' in s and 'CommittedBodies() <= 60' in s
|
|
assert 'm_InitialLedger + 5' in s and s.count('!hq.StartConvoy()')==2
|
|
smoke=(ROOT/'addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c').read_text()
|
|
assert 'm_ERRTestConvoy = outcome == "convoy"' in smoke and 'm_ERRSmokeStep = 106' in smoke
|
|
# Both convoy variants must enter the normal running phase before waiting for
|
|
# mortar StartupActivated; otherwise the command tick is paused in prison.
|
|
branch=smoke[smoke.index('if (m_ERRTestConvoy)', smoke.index('if (m_ERRSmokeStep == 0)')):]
|
|
branch=branch[:branch.index('m_ERRSmokeStep = 106;')]
|
|
assert branch.count('UnlockPrison(m_ERRSmokePlayer)')==1
|
|
# Prevent unrelated opening hunters before the capped legacy convoy is admitted.
|
|
assert branch.count('ERR_HQ.Get().Hunters().Stop()') == 1
|
|
assert branch.index('ERR_HQ.Get().Hunters().Stop()') < branch.index('UnlockPrison(m_ERRSmokePlayer)')
|
|
assert branch.index('UnlockPrison(m_ERRSmokePlayer)') < branch.index('if (convoyOutcome == "supply-convoys")')
|
|
runner=ROOT/'tools/headless_workbench.py'
|
|
for extra in (['--project','core','--rounds','1','--timeout','600'],
|
|
['--project','chat','--rounds','2','--timeout','600'],
|
|
['--project','chat','--rounds','1','--timeout','599']):
|
|
result=subprocess.run([sys.executable,str(runner),'--smoke','convoy','--compat','/tmp/erri-unused-convoy-compat',
|
|
'--profile','/tmp/erri-unused-convoy-profile',*extra],capture_output=True,text=True)
|
|
assert result.returncode==2 and 'convoy requires Chat' in result.stderr,result.stderr
|
|
print('PASS: actual convoy motion thresholds, native-only proof boundaries, physical cargo/crew ownership and pre-launch runner restrictions')
|