Advance standalone admission, finite artillery and native validation

This commit is contained in:
2026-09-19 09:02:31 +02:00
parent af5146a317
commit 40a474934c
532 changed files with 56456 additions and 199 deletions
@@ -0,0 +1,19 @@
from pathlib import Path
from policy_harness import body,run
ROOT=Path(__file__).resolve().parents[1]
s=body(ROOT/'addons/ai/Scripts/Game/ERR/ERR_HelicopterAvailability.c','string Check(')
run('#include <string>\n#include <cassert>\nusing std::string;\nstruct Availability {float m_fGroundedSince=-1;\n'+s+'''};
int main(){
Availability a;
assert(a.Check(0,0,false,false,true,false,false,0,0).empty());
assert(!a.Check(0,0,true,false,true,false,false,0,0).empty());
assert(a.Check(20000,0,false,false,true,false,false,0,0).empty());
assert(a.Check(79999,0,false,false,true,false,false,0,0).empty());
assert(!a.Check(80000,0,false,false,true,false,false,0,0).empty());
assert(a.Check(81000,0,false,false,true,true,false,0,0).empty());
assert(a.Check(82000,0,false,false,true,false,true,0,0).empty());
assert(!a.Check(82000,0,false,true,true,false,false,0,0).empty());
assert(!a.Check(82000,0,false,false,false,false,false,0,0).empty());
}
''')
print('PASS: migrated aircraft availability policy (controller migration still pending)')
@@ -0,0 +1,77 @@
#!/usr/bin/env python3
"""Execute production bounded radio graph and hop-delivery state machine."""
from pathlib import Path
import re, subprocess, tempfile
ROOT=Path(__file__).resolve().parents[1]
source=(ROOT/'addons/ai/Scripts/Game/ERR/ERR_HQNetwork.c').read_text()
def extract(signature):
a=source.index(signature);b=source.index('{',a);end=b+1;depth=1
while depth:depth+=(source[end]=='{')-(source[end]=='}');end+=1
return source[a:end]
def trans(s):
s=re.sub(r'//[^\n]*','',s).replace('protected ','').replace('null','nullptr')
s=s.replace('string.Format','Format').replace('string ', 'std::string ')
s=s.replace('Math.Round(distance).ToString()', 'std::to_string(int(distance))')
s=re.sub(r'\b(\w+)\.ToString\(\)',r'std::to_string(\1)',s)
for name in ['Math','vector']:s=s.replace(name+'.',name+'::')
for typ in ['IEntity','SCR_AIGroup','ERR_HQRoute','ERR_HQRadioNode','ERR_HQJournal']:
s=re.sub(r'\b'+typ+r' (\w+)',typ+r'* \1',s)
s=s.replace('array<int> queue = {}','Arr<int> queue').replace('array<int> cell','Arr<int>* cell').replace('array<int> neighbors','Arr<int>* neighbors')
s=s.replace('cell = {};','cell = new Arr<int>();')
s=re.sub(r'foreach\s*\(int (\w+) : neighbors\)',r'for (auto \1 : *neighbors)',s)
for name in ['carrier','caller','node','route','journal','cell']:
s=s.replace(name+'.',name+'->')
s=re.sub(r'(Nodes|m_Nodes)\[([^\]]+)\]\.',r'\1[\2]->',s)
s=s.replace('Carrier.GetOrigin()', 'Carrier->GetOrigin()')
s=re.sub(r'\b(int|float|bool) (\w+);',r'\1 \2{};',s)
return s
headers=r'''
#include <cassert>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <iostream>
struct vector{float v[3]{};float operator[](int i)const{return v[i];}static float DistanceXZ(vector a,vector b){return std::hypot(a[0]-b[0],a[2]-b[2]);}};
vector V(float x,float z=0){return {{x,0,z}};}
namespace Math{int Floor(float x){return std::floor(x);}}
std::string Format(const char*,int x,int z){return std::to_string(x)+":"+std::to_string(z);}
template<class T>struct Arr:std::vector<T>{int Count(){return this->size();}bool IsEmpty(){return this->empty();}void Clear(){this->clear();}void Insert(T x){this->push_back(x);}void InsertAt(T x,int i){this->insert(this->begin()+i,x);}};
template<class K,class V>struct Map:std::map<K,V>{void Clear(){this->clear();}bool Contains(K k){return this->count(k);}bool Find(K k,V& v){if(!Contains(k))return false;v=this->at(k);return true;}V Get(K k){if(!Contains(k))return {};return this->at(k);}void Insert(K k,V v){(*this)[k]=v;}};
struct SCR_AIGroup{bool enemy=true;};struct IEntity{vector pos;bool alive=true;int radio=1;bool captured=false;vector GetOrigin(){return pos;}};
struct ERR_HQRadioNode{IEntity* Carrier{};SCR_AIGroup* Group{};int UnitId{},Capability{};bool Valid(bool manpack=false){return Carrier&&Carrier->alive&&!Carrier->captured&&Carrier->radio>=(manpack?2:1);}std::string Label(){return "unit "+std::to_string(UnitId);}};
struct ERR_HQJournal{Arr<std::string> events;void Write(std::string kind,std::string text,int){events.Insert(kind+" "+text);}};
'''
routefields='Arr<ERR_HQRadioNode*> Nodes;bool Downlink{},Sending{},Failed{};int Cursor{},MessageId{};float Due{},StartedAt=-1;vector SentFrom;std::string Payload;'
networkfields='Arr<ERR_HQRadioNode*> m_Nodes;Arr<int> m_Parents,m_Depths;Map<IEntity*,int> m_Indices;Map<std::string,Arr<int>*> m_Cells;bool Overflow{};'
route='struct ERR_HQRoute{'+routefields+'\n'+'\n'.join(trans(extract(x)) for x in ['int Advance(', 'protected string SenderLabel(', 'protected int Fail('])+'};\n'
network='struct Network{'+networkfields+'\n'+'\n'.join(trans(extract(x)) for x in ['void Clear(', 'protected string Cell(', 'void Add(', 'void Build(', 'ERR_HQRoute Route('])+'};\n'
tests=r'''
int main(){
Network network;SCR_AIGroup group;IEntity c[5];for(int i=0;i<5;i++)c[i].pos=V(i*500);
c[0].radio=2;for(int i=0;i<5;i++)network.Add(&c[i],&group,37+i,c[i].radio);network.Build();
assert(network.Route(&c[0])->Nodes.Count()==1);assert(network.Route(&c[3])->Nodes.Count()==4);assert(!network.Route(&c[4]));
ERR_HQJournal journal;auto up=network.Route(&c[2]);assert(up->Nodes.Count()==3);
assert(up->Advance(0,&journal)==0);assert(up->Advance(1999,&journal)==0);assert(up->Advance(2000,&journal)==0);
c[2].alive=false;assert(up->Advance(4000,&journal)==0);c[0].alive=false;assert(up->Advance(6000,&journal)==1);
assert(journal.events.back().find("HQ received")!=std::string::npos); // cannot recall an emitted uplink
for(auto& carrier:c)carrier.alive=true;
auto lost=network.Route(&c[2]);assert(lost->Advance(0,&journal)==0);c[1].radio=0;assert(lost->Advance(2000,&journal)==-1);assert(lost->Advance(4000,&journal)==-1);
c[1].radio=1;auto moving=network.Route(&c[2]);moving->Advance(0,&journal);c[1].pos=V(499);assert(moving->Advance(2000,&journal)==-1);c[1].pos=V(500);
auto down=network.Route(&c[2],true);assert(down->Nodes[0]->Carrier==&c[0]);assert(down->Advance(0,&journal)==0);
assert(down->Advance(2000,&journal)==0);assert(down->Advance(4000,&journal)==0);assert(down->Advance(6000,&journal)==1);
auto captured=network.Route(&c[2],true);captured->Advance(0,&journal);c[0].captured=true;assert(captured->Advance(2000,&journal)==-1);c[0].captured=false;
auto timeout=network.Route(&c[2]);timeout->Advance(0,&journal);assert(timeout->Advance(30001,&journal)==-1);
Network disconnected;disconnected.Add(&c[1],&group,1,1);disconnected.Build();assert(!disconnected.Route(&c[1]));
Network boundary;c[1].pos=V(501);boundary.Add(&c[0],&group,1,2);boundary.Add(&c[1],&group,2,1);boundary.Build();assert(!boundary.Route(&c[1]));
network.Clear();assert(!network.Route(&c[0]));
Network crowded;std::vector<IEntity> many(2050);for(auto& carrier:many){carrier.radio=2;crowded.Add(&carrier,&group,1,2);}assert(crowded.Overflow&&crowded.m_Nodes.Count()==2048);
crowded.Build();assert(crowded.Overflow); // bounded dense graph work
std::cout<<"PASS: real-carrier shortest-hop paths, 500m boundary, three-hop cap, no-manpack failure, hop timing, emitted-message survival, radio loss, capture, motion, timeout, reset and network bounds\n";
}
'''
with tempfile.TemporaryDirectory(prefix='eai-hq-network-') as tmp:
cpp=Path(tmp)/'test.cpp';exe=Path(tmp)/'test';cpp.write_text(headers+route+network+tests)
subprocess.run(['g++','-std=c++17','-Wall','-Wextra',str(cpp),'-o',str(exe)],check=True)
subprocess.run([str(exe)],check=True)
@@ -0,0 +1,21 @@
from pathlib import Path
from policy_harness import body,run
ROOT=Path(__file__).resolve().parents[1]
s=body(ROOT/'addons/ai/Scripts/Game/ERR/ERR_MortarSalvo.c','static vector Offset(').replace('Math.','Math::')
run('''#include <cassert>
#include <cmath>
struct vector { float x,y,z;};
vector Vector(float x,float y,float z){return {x,y,z};}
namespace Math {constexpr float DEG2RAD=0.01745329252;float Sqrt(float n){return std::sqrt(n);}float Sin(float n){return std::sin(n);}float Cos(float n){return std::cos(n);}}
constexpr int ROUNDS=8;constexpr float RADIUS_METRES=40;
'''+s+'''
int main(){for(int site=0;site<4;site++)for(int order=0;order<10;order++){
float previous=0;
for(int shot=0;shot<8;shot++){
auto a=Offset(site,order,shot),b=Offset(site,order,shot);
assert(a.x==b.x&&a.z==b.z&&a.y==0);
float radius=std::hypot(a.x,a.z);assert(radius>previous&&radius<=40.0001);previous=radius;
}
}}
''')
print('PASS: migrated salvo offsets are deterministic, spread and bounded (firing controller pending)')
@@ -0,0 +1,14 @@
"""Execute actual Enforce policy bodies as C++, without claiming engine coverage."""
from pathlib import Path
import subprocess,tempfile,re
ROOT=Path(__file__).resolve().parents[1]
def body(path,signature):
s=path.read_text();a=s.index(signature);b=s.index('{',a);i=b+1;depth=1
while depth:
depth+=(s[i]=='{')-(s[i]=='}');i+=1
return s[a:i]
def run(code):
with tempfile.TemporaryDirectory(prefix='err-policy-') as tmp:
p=Path(tmp);(p/'check.cpp').write_text(code)
subprocess.run(['g++','-std=c++17','-Wall','-Werror',str(p/'check.cpp'),'-o',str(p/'check')],check=True)
subprocess.run([str(p/'check')],check=True)
@@ -0,0 +1,35 @@
"""Exercise actual Core alias, integer parsing and settings-boundary bodies.
Native dispatch/storage and remote ownership remain separate tests.
"""
from policy_harness import ROOT,body,run
admin=ROOT/'addons/core/Scripts/Game/ERR/ERR_AdminService.c'
settings=ROOT/'addons/core/Scripts/Game/ERR/ERR_Settings.c'
rules='\n'.join(body(path,sig) for path,sig in ((admin,'static string CoreSetting('),(admin,'static bool Integer('),(settings,'static bool Valid(')))
rules=(rules.replace('string ', 'std::string ').replace('out int ', 'int& ')
.replace('text.Length()', 'int(text.size())').replace('.IsEmpty()', '.empty()')
.replace('.Substring(', '.substr(').replace('"0123456789".IndexOf(', 'std::string("0123456789").find(')
.replace(' < 0) return false;', ' == std::string::npos) return false;').replace('text.ToInt()', 'std::stoi(text)'))
run('#include <cassert>\n#include <string>\n'+rules+r'''
int main(){
assert(CoreSetting("intel","reveal")=="intelRevealChancePercent");
assert(CoreSetting("mission","radio")=="radioDefenceSeconds");
for(std::string section:{"", "hq", "mission", "intel", "unknown"})
for(std::string option:{"", "interval", "carrying", "radio", "reveal", "unknown"}){
bool recognized=(section=="intel"&&option=="reveal")||(section=="mission"&&option=="radio");
assert(CoreSetting(section,option).empty()==!recognized);
}
int parsed=-1;
for(std::string malformed:{"", "-1", "+1", "1.0", "10junk", "1e2", "0x10", " 50", "50 ", "1234567"})
assert(!Integer(malformed,parsed));
for(int value=0;value<=101;++value){
assert(Integer(std::to_string(value),parsed)&&parsed==value);
assert(Valid(CoreSetting("intel","reveal"),parsed)==(value<=100));
}
assert(Integer("000050",parsed)&&parsed==50);
assert(Integer("999999",parsed)&&!Valid("intelRevealChancePercent",parsed));
assert(!Valid("intelRevealChancePercent",-1));
assert(Valid("radioDefenceSeconds",30)&&Valid("radioDefenceSeconds",1800));
assert(!Valid("radioDefenceSeconds",29)&&!Valid("radioDefenceSeconds",1801));
}
''')
print('PASS: Core document-discovery alias, companion-only alias exclusion, strict integer parsing and setting boundaries')
@@ -0,0 +1,17 @@
from policy_harness import ROOT, body, run
import re
source = body(ROOT/'addons/core/Scripts/Game/ERR/ERR_CasualtyGroundSupport.c', 'static bool SupportHit(')
source = re.sub(r'(?<![\w.])(\d+\.\d+)(?![\w.])', r'\1f', source)
run('#include <cassert>\n' + source + '''
int main() {
assert(SupportHit(0,1,false,false));
assert(SupportHit(0.999,0.85,false,false));
assert(!SupportHit(1,1,false,false)); // no hit is no support
assert(!SupportHit(-0.01,1,false,false));
assert(!SupportHit(0.5,0.849,false,false));
assert(!SupportHit(0.5,-1,false,false));
assert(!SupportHit(0.5,1,true,false)); // own landing gear cannot support itself
assert(!SupportHit(0.5,1,false,true)); // player/vehicle is not static parking support
}
''')
print('PASS: actual short-cast hit, upward support normal, no self support and no dynamic support')
@@ -0,0 +1,45 @@
"""Run the actual fixture method against a narrow native-damage API fake."""
from policy_harness import ROOT, body, run
p=ROOT/'addons/core/Scripts/Game/ERR/ERR_NativeCasualtyLoadProbe.c'
method=body(p,'protected bool IncapacitateGroundCasualty(')
method=method.replace('protected bool','bool').replace('m_Damage.','m_Damage->').replace('resilience.','resilience->').replace('ERR_Actors.','ERR_Actors::').replace('null','nullptr')
run('''
#include <cassert>
#include <initializer_list>
struct NativeHitZone { float health=100; float GetHealth(){return health;} };
using HitZone=NativeHitZone*;
struct Actor { bool alive=true; };
struct Damage {
NativeHitZone resilience; bool enabled=true, missing=false, swallow=false; int forces=0;
HitZone GetResilienceHitZone(){return missing ? nullptr : &resilience;}
bool IsDamageHandlingEnabled(){return enabled;}
void EnableDamageHandling(bool value){enabled=value;}
void ForceUnconsciousness(){forces++; if(enabled && !swallow)resilience.health=0;}
};
struct ERR_Actors {static bool Alive(Actor* actor){return actor && actor->alive;}};
Actor* m_Casualty; Damage* m_Damage;
bool Check(bool value,const char*){return value;}
template<class... Args> void PrintFormat(const char*,Args...){}
'''+method+'''
int main(){
Actor actor; m_Casualty=&actor;
for(bool original:{false,true}) {
Damage damage; m_Damage=&damage; damage.enabled=original;
assert(IncapacitateGroundCasualty());
assert(damage.forces==1 && damage.resilience.health==0 && actor.alive);
assert(damage.enabled==original);
// No second artificial reduction: already-zero initial state must fail.
assert(!IncapacitateGroundCasualty());
assert(damage.enabled==original);
}
Damage blocked; blocked.enabled=false; blocked.swallow=true; m_Damage=&blocked;
assert(!IncapacitateGroundCasualty());
assert(blocked.forces==1 && !blocked.enabled && actor.alive);
Damage missing; missing.missing=true; m_Damage=&missing;
assert(!IncapacitateGroundCasualty() && missing.forces==0);
m_Damage=nullptr; assert(!IncapacitateGroundCasualty());
Damage dead; m_Damage=&dead; actor.alive=false;
assert(!IncapacitateGroundCasualty() && dead.forces==0);
}
''')
print('PASS: actual fixture method permits one native resilience operation and restores either prior protection state, including failure paths')
@@ -0,0 +1,41 @@
from policy_harness import ROOT, body, run
import re
path = ROOT/'addons/core/Scripts/Game/ERR/ERR_CasualtyLoadingService.c'
source = '\n'.join(body(path, signature) for signature in [
'static int RoundAction(', 'static bool ObserveTicket(', 'static bool Within(', 'static bool SettledFor(', 'static bool Ranges(', 'static bool AircraftMotion('])
# Enforce float literals are single precision; C++ otherwise promotes these to doubles.
source = re.sub(r'(?<![\w.])(\d+\.\d+)(?![\w.])', r'\1f', source)
source = source.replace('ERR_Phase.PREPARING', '0').replace('ERR_MissionRules.Terminal(phase)', '(phase == 5 || phase == 6)')
run('#include <cassert>\n' + source + '''
int main() {
assert(RoundAction(0)==0); // pre-start roster callbacks must not latch Stop
for (int phase=1;phase<=4;phase++) assert(RoundAction(phase)==1);
assert(RoundAction(5)==2); assert(RoundAction(6)==2);
for (int flags=0;flags<8;flags++) {
bool committed=flags&1, physical=flags&2, authorized=flags&4;
bool keep=physical && (committed || authorized);
assert(ObserveTicket(committed,physical,authorized)==keep);
}
assert(ObserveTicket(true,true,false)); // disconnect after irreversible commit retains seat
assert(!ObserveTicket(false,true,false)); // before commit it cancels
// A late/reordered/expired lease cannot authorize a native entry.
assert(Within(1000,1000,3000)); assert(Within(1000,3999,3000));
assert(!Within(1000,4000,3000)); assert(!Within(1000,999,3000));
assert(!Within(2147483000,-2147483000,3000));
// A continuous observation window needs both sufficient settling and fresh data.
assert(!SettledFor(-1,5000,5000)); assert(!SettledFor(1000,5999,5999));
assert(SettledFor(1000,6000,6000)); assert(SettledFor(1000,6000,7999));
assert(!SettledFor(1000,6000,8000)); assert(!SettledFor(1000,6000,5999));
assert(!SettledFor(6000,6000,6000)); // recovered/moving body starts a new window
// Every participant must independently be inside the physical rescue range.
assert(Ranges(3,12,12)); assert(!Ranges(3.01,12,12));
assert(!Ranges(3,12.01,12)); assert(!Ranges(3,12,12.01));
assert(!Ranges(-1,0,0)); assert(!Ranges(0,-1,0)); assert(!Ranges(0,0,-1));
// Contact alone cannot authorize an airborne, inverted, sliding or turning craft.
assert(AircraftMotion(true,1,0,0)); assert(AircraftMotion(true,0.85,0.5,0.1));
assert(!AircraftMotion(false,1,0,0)); assert(!AircraftMotion(true,-1,0,0));
assert(!AircraftMotion(true,0.849,0,0)); assert(!AircraftMotion(true,1,0.501,0));
assert(!AircraftMotion(true,1,0,0.101));
}
''')
print('PASS: rescue lease expiry/reordering, fresh five-second settling, independent rescue ranges and grounded upright aircraft motion boundaries')
@@ -0,0 +1,43 @@
"""Fixture boundaries and actual safe-exit policy; not an engine substitute."""
from policy_harness import ROOT, body, run
import re
source = ROOT/'addons/core/Scripts/Game/ERR/ERR_NativeCasualtyRemoveProbe.c'
method = body(source,'static bool SafeExit(')
method = re.sub(r'(?<![\w.])(\d+\.\d+)(?![\w.])',r'\1f',method)
run('#include <cassert>\n'+method+'''
int main() {
assert(SafeExit(0,0));
assert(SafeExit(1.25,-0.25));
assert(SafeExit(1.25,1.5));
assert(!SafeExit(1.251,0));
assert(!SafeExit(-0.01,0));
assert(!SafeExit(1,-0.251));
assert(!SafeExit(1,1.501));
}
''')
text=source.read_text()
assert text.startswith('#ifdef WORKBENCH')
assert 'GetContextIndex("door_l01_door") >= 0' in text
assert 'actions.Contains(m_Remove)' in text
assert 'PickDoorIndexForPoint(m_Context.GetOrigin())' in text
assert 'GetExitTeleportPointInfo()' in text
assert 'm_Remove.GetActionDuration() == 1' in text
assert 'm_Remove.CanBeShown(m_Caller)' in text and 'm_Remove.CanBePerformed(m_Caller)' in text
assert text.count('m_Remove.PerformAction(') == 1
assert 'm_Remove.SetCompartmentDoorInfoIndex(m_SavedDoor)' in body(source,'override void Cleanup(')
assert 'if (m_RemoveStopped) return -1;' in body(source,'override int Tick(')
for forbidden in ('GetOutVehicle(', 'GetOutVehicle_NoDoor(', 'KickFromVehicle(', 'SetUnconscious(', 'm_Casualty.Set', 'm_Casualty).Teleport', 'SetActive('):
assert forbidden not in text,forbidden
# Existing arbitrary-ground mechanism remains exactly its original contract.
base=ROOT/'addons/core/Scripts/Game/ERR/ERR_NativeCasualtyLoadProbe.c'
assert 'GetOutVehicle_NoDoor(exitTransform, true, false)' in body(base,'protected bool BeginExit(')
assert 'exitTransform[3] = m_GroundPosition;' in body(base,'protected bool BeginExit(')
assert body(base,'protected bool ExitSettled(').strip().endswith('return ERR_Actors.Alive(m_Casualty) && vector.Distance(m_Casualty.GetOrigin(), m_GroundPosition) < 4 && m_Seat.IsCompartmentAccessible();\n }')
base_text=(ROOT/'addons/core/Scripts/Game/ERR/ERR_NativeBaseSmoke.c').read_text()
assert base_text.count('m_ERRExtractionCase == "casualty-remove"') == 3
assert 'm_ERRCasualtyLoadProbe = new ERR_NativeCasualtyRemoveProbe(this);' in base_text
assert 'm_ERRBaseStep = 802; Transition(ERR_Phase.DEFEAT);' in base_text
runner=(ROOT/'tools/headless_workbench.py').read_text()
assert runner.count("'casualty-remove'") == 3
compile(runner,'headless_workbench.py','exec')
print('PASS: actual safe-exit boundary policy, native action/door selection, stop/cache cleanup, separate old mechanism and opt-in runner contracts')
@@ -0,0 +1,43 @@
"""Exercise the production structural-ticket check after post-commit death.
No synthetic fixture is claimed as network/owner-RPC proof.
"""
from policy_harness import ROOT, body, run
path = ROOT/'addons/core/Scripts/Game/ERR/ERR_CasualtyLoadingService.c'
physical = body(path, 'protected bool PhysicalTicket(')
physical = (physical.replace('protected ', '').replace('ERR_CasualtyLoadTicket ticket', 'Ticket* ticket')
.replace('ticket.', 'ticket->').replace('m_Mode.', 'm_Mode->')
.replace('ERR_Phase.EXTRACTION', '4').replace('ERR_Actors.Alive', 'Alive')
.replace('ERR_CasualtyLoadingRules.TransportBench', 'TransportBench').replace('null', 'nullptr'))
policy = '\n'.join(body(path, signature) for signature in ['static bool ObserveTicket(', 'static bool Within('])
run('''#include <cassert>
struct Entity { bool alive=true; };
bool Alive(Entity* entity){return entity && entity->alive;}
bool TransportBench(Entity* seat,Entity* aircraft){return seat && aircraft;}
struct Ticket { Entity* Aircraft; Entity* Casualty; Entity* Seat; };
struct Mode {
Entity* aircraft; bool active=true; int phase=4;
bool Active(){return active;} int Phase(){return phase;}
Entity* ExtractionVehicle(){return aircraft;}
};
''' + policy + '''
struct Service { Mode* m_Mode;
''' + physical + '''
};
int main(){
Entity aircraft, body, bench; Mode mode{&aircraft}; Service service{&mode};
Ticket ticket{&aircraft,&body,&bench};
assert(service.PhysicalTicket(&ticket));
body.alive=false; // server death after authorization; owner commit can still be in flight
assert(service.PhysicalTicket(&ticket));
assert(ObserveTicket(true,service.PhysicalTicket(&ticket),false));
assert(!ObserveTicket(false,service.PhysicalTicket(&ticket),false));
assert(Within(1000,8999,8000)); // keep observation reservation through its budget
assert(!Within(1000,9000,8000)); // eventually release, without another owner command
ticket.Casualty=nullptr; assert(!service.PhysicalTicket(&ticket));
ticket.Casualty=&body; ticket.Seat=nullptr; assert(!service.PhysicalTicket(&ticket));
ticket.Seat=&bench; aircraft.alive=false; assert(!service.PhysicalTicket(&ticket));
aircraft.alive=true; mode.active=false; assert(!service.PhysicalTicket(&ticket));
mode.active=true; mode.phase=5; assert(!service.PhysicalTicket(&ticket));
}
''')
print('PASS: actual committed-ticket structure preserves reservation after death, rejects missing bodies/seats and ends at observation expiry')
@@ -0,0 +1,44 @@
"""Execute the actual opt-in Load body; no native engine or GUI is launched."""
from policy_harness import ROOT, body, run
source=ROOT/'addons/core/Scripts/GameLib/ERR/ERR_DiagnosticNoSplash.c'
load=body(source,'override void Load()').replace('override void','void').replace('System.','System::').replace('super.Load()', 'Base::Load()')
run('''#include <cassert>
#include <string>
using string=std::string;
struct System {
static bool noSplash, explicitScenario;
static string project;
static bool IsCLIParam(const char*) { return noSplash; }
static bool GetCLIParam(const char*, string& value) {value=project;return explicitScenario;}
};
bool System::noSplash=false; bool System::explicitScenario=false; string System::project;
int diagnostics=0;
void Print(const char*) {diagnostics++;}
struct Base {
int nativeLoads=0, s_iSplashShown=0;
void Load(){nativeLoads++;s_iSplashShown++;}
};
struct Subject:Base {
bool m_ERRDiagnosticSplashSkipped=false;
''' + load + '''
};
int main(){
for(bool flag:{false,true}) for(bool explicitRequest:{false,true})
for(const string& project:{string("core"),string("chat"),string(""),string("other")}) {
System::noSplash=flag;System::explicitScenario=explicitRequest;System::project=project;
diagnostics=0;Subject instance;
instance.Load();instance.Load();instance.Load();
bool selected=flag && explicitRequest && (project=="core" || project=="chat");
assert(instance.nativeLoads==(selected ? 0 : 3));
assert(instance.s_iSplashShown==(selected ? 1 : 3));
assert(diagnostics==(selected ? 1 : 0));
assert(instance.m_ERRDiagnosticSplashSkipped==selected);
}
// Recreated splash instance on addon reload remains independently bounded.
System::noSplash=true;System::explicitScenario=true;System::project="core";
Subject first,reloaded;diagnostics=0;
first.Load();reloaded.Load();reloaded.Load();
assert(first.s_iSplashShown==1 && reloaded.s_iSplashShown==1 && diagnostics==2);
}
''')
print('PASS: actual noSplash Load body requires both explicit diagnostic and noSplash, preserves vanilla otherwise, and handles repeated Load/reload')
@@ -0,0 +1,51 @@
"""Execute actual environment parsing/formatting and settings policy bodies.
Calendar validity expectations come from Python's independent datetime calendar.
"""
from datetime import date
import re
from policy_harness import ROOT, body, run
settings = ROOT/'addons/core/Scripts/Game/ERR/ERR_Settings.c'
service = ROOT/'addons/core/Scripts/Game/ERR/ERR_EnvironmentService.c'
admin = ROOT/'addons/core/Scripts/Game/ERR/ERR_AdminService.c'
def translate(source):
source = (source.replace('string ', 'std::string ').replace('out int ', 'int& ')
.replace('text.Length()', 'int(text.size())').replace('.IsEmpty()', '.empty()')
.replace('.Substring(', '.substr(')
.replace('"0123456789".IndexOf(', 'std::string("0123456789").find(')
.replace(' < 0) return false;', ' == std::string::npos) return false;')
.replace('text.ToInt()', 'std::stoi(text)')
.replace('ERR_CommandArguments.Integer', 'Integer').replace('ERR_Settings.Valid', 'Valid'))
return re.sub(r'(\w+)\.ToString\(\)', r'std::to_string(\1)', source)
functions='\n'.join(translate(body(path, sig)) for path, sig in (
(settings,'static bool Valid('), (settings,'static int AddedDefault('),
(admin,'static bool Integer('), (service,'static string Pad2('),
(service,'static string Date('), (service,'static bool ParseDate('),
(service,'static string ProfileName('), (service,'static string WeatherStateName('),
(service,'static bool ParseProfile('),
))
cases=[]
# Every calendar boundary in range, including leap/century rules and malformed days.
for year in range(1900,2051):
for month in range(1,13):
for day in (0,1,28,29,30,31,32):
code=(year-1900)*10000+month*100+day
text=f'{year:04}-{month:02}-{day:02}'
try: date(year,month,day); valid=True
except ValueError: valid=False
cases.append(f'{{{code},"{text}",{str(valid).lower()}}}')
run('#include <cassert>\n#include <string>\n'+functions+'\nstruct Case {int code; const char* text; bool valid;};\nstatic Case cases[]={' + ','.join(cases) + '};\nint main(){int parsed=-1;' + r'''
for (auto c:cases) {assert(Valid("startDateCode",c.code)==c.valid); assert(ParseDate(c.text,parsed)==c.valid); if(c.valid)assert(parsed==c.code && Date(parsed)==c.text);}
assert(AddedDefault("startDateCode")==0 && AddedDefault("weatherProfile")==0);
assert(Valid("startDateCode",0) && Date(0)=="authored" && ParseDate("authored",parsed) && parsed==0);
for(std::string text:{"1900-00-00","1900-00-01","2050-13-01","1899-12-31","2051-01-01","1989-6-01","1989-06-1","1989-06-01junk"," 1989-06-01","1989-06-01 ","198a-06-01","", "1989/06/01"}) assert(!ParseDate(text,parsed));
assert(!Valid("startDateCode",-1) && !Valid("startDateCode",1501232));
for(int p=0;p<=3;p++){assert(Valid("weatherProfile",p)); assert(ParseProfile(ProfileName(p),parsed)&&parsed==p);}
assert(ParseProfile("rainy",parsed)&&parsed==3);
assert(!ParseProfile("random",parsed)&&!ParseProfile("storm",parsed));
assert(!Valid("weatherProfile",-1)&&!Valid("weatherProfile",4));
assert(WeatherStateName(0)=="" && WeatherStateName(1)=="Clear" && WeatherStateName(2)=="Overcast" && WeatherStateName(3)=="Rainy");
}
''')
print('PASS: native settings policy matches calendar boundaries 1900-2050, date/profile parsing is strict, authored defaults preserve old worlds')
@@ -0,0 +1,62 @@
#!/usr/bin/env python3
"""Negative runner checks stop before any native process/audio initialization."""
from pathlib import Path
import subprocess
import sys
import tempfile
import unittest
ROOT = Path(__file__).resolve().parents[1]
class EnvironmentRestartRunnerTests(unittest.TestCase):
def invoke(self, profile, *extra):
return subprocess.run([sys.executable, str(ROOT/'tools/headless_workbench.py'),
'--compat', str(profile/'missing-prefix'), '--profile', str(profile),
'--smoke', 'environment-restart', '--project', 'core', '--rounds', '2',
*extra], text=True, capture_output=True)
def test_requires_two_core_rounds(self):
with tempfile.TemporaryDirectory() as directory:
for extra in [('--rounds','1'), ('--rounds','3'), ('--project','chat')]:
with self.subTest(extra=extra):
result = self.invoke(Path(directory), *extra)
self.assertNotEqual(result.returncode, 0)
self.assertIn('requires --project core --rounds 2', result.stderr)
def test_every_existing_fixture_file_is_refused_and_preserved(self):
for name in ['erri-environment-restart.json', 'erri-environment-restart.json.bak',
'erri-environment-restart.json.tmp', 'erri-environment-restart-round.json']:
with self.subTest(name=name), tempfile.TemporaryDirectory() as directory:
profile = Path(directory)
path = profile/name
path.write_text('prior evidence')
result = self.invoke(profile)
self.assertNotEqual(result.returncode, 0)
self.assertIn('fixture paths must not preexist', result.stderr)
self.assertEqual(path.read_text(), 'prior evidence')
def test_broken_fixture_symlink_is_refused(self):
with tempfile.TemporaryDirectory() as directory:
profile = Path(directory)
(profile/'erri-environment-restart.json').symlink_to(profile/'missing-target')
result = self.invoke(profile)
self.assertIn('fixture paths must not preexist', result.stderr)
self.assertTrue((profile/'erri-environment-restart.json').is_symlink())
def test_empty_fixture_reaches_existing_prefix_guard_without_side_effects(self):
with tempfile.TemporaryDirectory() as directory:
profile = Path(directory)
result = self.invoke(profile)
self.assertNotEqual(result.returncode, 0)
self.assertIn('must be a disposable cloned prefix', result.stderr)
self.assertEqual(list(profile.iterdir()), [])
def test_existing_environment_outcome_does_not_acquire_restart_path_policy(self):
with tempfile.TemporaryDirectory() as directory:
profile = Path(directory)
(profile/'erri-environment-restart.json').write_text('prior evidence')
result = self.invoke(profile, '--smoke', 'environment', '--rounds', '1')
self.assertIn('must be a disposable cloned prefix', result.stderr)
self.assertNotIn('fixture paths must not preexist', result.stderr)
if __name__ == '__main__': unittest.main()
@@ -0,0 +1,51 @@
"""Execute production time policies; do not claim native simulation coverage."""
from policy_harness import ROOT, body, run
source = ROOT/'addons/core/Scripts/Game/ERR/ERR_ExtractionPlacement.c'
methods = '\n'.join(body(source, signature) for signature in (
'static bool CanWake(', 'static bool Fresh(', 'static bool QualificationAllowed(', 'static bool Stable('))
run('#include <cassert>\n' + methods + '''
int main() {
assert(CanWake(true,0,0,30000));
assert(CanWake(true,0,29999,30000));
assert(!CanWake(false,0,1,30000));
assert(!CanWake(true,1,1,30000)); // activation cannot be repeated
assert(!CanWake(true,2,1,30000));
assert(!CanWake(true,0,30000,30000)); // no wake after expired preparation
assert(!CanWake(true,0,30001,30000));
assert(QualificationAllowed(false,29999,30000));
assert(!QualificationAllowed(false,30000,30000)); // exactly deadline is not first qualification
assert(!QualificationAllowed(false,30001,30000));
assert(QualificationAllowed(true,30000,30000)); // continuous monitoring may outlive settling
assert(QualificationAllowed(true,90000,30000));
assert(!Fresh(-1,0));
assert(!Fresh(1000,999));
assert(Fresh(1000,2500));
assert(!Fresh(1000,2501)); // delayed callbacks restart the stability window
assert(!Stable(-1,1000,2000));
assert(!Stable(1000,999,2000));
assert(!Stable(1000,1750,1999));
assert(Stable(1000,1750,2000));
assert(!Stable(1000,1000,2501));
assert(!Stable(1000,2000,1999));
}
''')
text = source.read_text()
poll = body(source, 'ERR_PrepareResult Poll(')
assert text.count('physics.SetActive(ActiveState.ACTIVE)') == 1
assert poll.index('!QualificationAllowed(') < poll.index('m_Result = ERR_PrepareResult.READY;')
assert poll.index('if (m_Stopped') < poll.index('physics.SetActive(')
assert poll.index('!Replication.IsServer()') < poll.index('physics.SetActive(')
assert poll.index('m_Mode.ExtractionVehicle() != m_Aircraft') < poll.index('physics.SetActive(')
assert poll.index('m_WakeCount = 1;') < poll.index('physics.SetActive(')
assert 'fuel.HasFuel() && ERR_CasualtyLoadingRules.AircraftReady(m_Aircraft)' in poll
for forbidden in ('SetVelocity(', 'SetAngularVelocity(', 'SetTransform(', 'SetWorldTransform(', 'Teleport(', 'ApplyImpulse', 'EnableDamageHandling('):
assert forbidden not in text, forbidden
site = (ROOT/'addons/core/Scripts/Game/ERR/ERR_SiteService.c').read_text()
assert 'if (m_ExtractionPlacement) m_ExtractionPlacement.Stop();' in site
assert 'Fail(m_ExtractionPlacement.FailureReason())' in site
assert 'pendingGuards > 0 || aircraftPlacement == ERR_PrepareResult.PENDING' in site
assert 'SetSpawnImmediately(false)' in site and 'PurgeSpawnRequestsForGroup' in site
probe = (ROOT/'addons/core/Scripts/Game/ERR/ERR_NativeCasualtyGroundProbe.c').read_text()
assert 'placement.Ready() && placement.WakeCount() == 1' in probe
assert 'SetActive(' not in probe
print('PASS: actual one-shot deadline/stability policies and preparation ownership, fuel, cleanup integration contracts')
@@ -0,0 +1,57 @@
"""Offline resource compatibility checks; these are not native loading tests."""
import hashlib
import re
import unittest
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
CORE = ROOT / "addons/core"
VANILLA_NORMALIZED_SHA256 = {
"US": "d8d16abbecadc6987ca7eed3b114446d0af5753535c891fcefc20d5b2d7db583",
"USSR": "2d3d3af74d0da33017ae3132c613fc9c19c0d20cd850a9830bb208db59e4bf25",
}
OLD_VEHICLES = {
"US": "{D83A5EFEEF6CBF61}Configs/EntityCatalog/US/Vehicles_EntityCatalog_US.conf",
"USSR": "{09C2ED5F617A0390}Configs/EntityCatalog/USSR/Vehicles_EntityCatalog_USSR.conf",
}
class FactionCatalogScopeTests(unittest.TestCase):
def test_only_vehicle_catalog_changes_from_installed_faction_profiles(self):
for side in ("US", "USSR"):
with self.subTest(side=side):
text = (CORE / f"Configs/ERR/Factions/{side}.conf").read_text()
restored, count = re.subn(
r"\{[A-F0-9]{16}\}Configs/ERR/Factions/MissionVehicles\.conf",
lambda _: OLD_VEHICLES[side], text,
)
self.assertEqual(count, 1)
# Pin every other vanilla field, including all inventory/group
# references, radio/identity/callsign/rank settings and base.
self.assertEqual(hashlib.sha256(restored.encode()).hexdigest(),
VANILLA_NORMALIZED_SHA256[side])
def test_vehicle_catalog_has_only_the_two_authored_assets(self):
text = (CORE / "Configs/ERR/Factions/MissionVehicles.conf").read_text()
self.assertRegex(text, r"^SCR_EntityCatalogMultiList\s*\{")
prefabs = re.findall(r'm_sEntityPrefab\s+"([^\"]+)"', text)
self.assertCountEqual(prefabs, [
"{259EE7B78C51B624}Prefabs/Vehicles/Wheeled/UAZ469/UAZ469.et",
"{DF5CCB7C0FF049F4}Prefabs/Vehicles/Helicopters/Mi8MT/Mi8MT_unarmed_transport.et",
])
self.assertEqual(len(prefabs), 2)
def test_world_uses_own_manager_without_full_vanilla_faction_inheritance(self):
manager = (CORE / "Prefabs/ERR/FactionManager.et").read_text()
self.assertIn("Prefabs/MP/Managers/Factions/FactionManager_Base.et", manager)
self.assertNotIn("FactionManager_USxUSSR.et", manager)
for side in ("US", "USSR"):
self.assertIn(f"Configs/ERR/Factions/{side}.conf", manager)
self.assertNotIn(f"Configs/Factions/{side}.conf", manager)
layer = (CORE / "Worlds/ERR_Everon_Layers/default.layer").read_text()
self.assertEqual(layer.count("Prefabs/ERR/FactionManager.et"), 1)
self.assertNotIn("FactionManager_USxUSSR.et", layer)
if __name__ == "__main__":
unittest.main()
@@ -0,0 +1,65 @@
"""Run actual ownership cancellation/Stop bodies with shared-array fixtures."""
from policy_harness import ROOT, body, run
p=ROOT/'addons/core/Scripts/Game/ERR/ERR_SiteService.c'
s='\n'.join(body(p, sig) for sig in ('void CancelInitialGuardRequests(', 'void Stop('))
for old,new in [
('GetGame().','GetGame()->'),
('ChimeraAIWorld world', 'ChimeraAIWorld* world'),
('ChimeraAIWorld.Cast', 'ChimeraAIWorld::Cast'),
('foreach (ERR_SiteRuntime site : m_Sites)', 'for (ERR_SiteRuntime* site : m_Sites)'),
('site.Group', 'site->Group'),
('site.InitialGuardCount', 'site->InitialGuardCount'),
('site->Group.', 'site->Group->'),
('new array<ResourceName>()', 'std::make_shared<Array<std::string>>()'),
('world.Purge', 'world->Purge'),
('m_ExtractionPlacement.', 'm_ExtractionPlacement->'),
('ERR_PrepareResult.', 'ERR_PrepareResult::'),
]: s=s.replace(old,new)
run('''#include <cassert>
#include <memory>
#include <string>
#include <vector>
template<typename T> using Array=std::vector<T>;
enum class ERR_PrepareResult {FAILED=-1,PENDING,READY};
struct Group {bool immediate=true; std::shared_ptr<Array<std::string>> m_aUnitPrefabSlots; int physical=0; void SetSpawnImmediately(bool b){immediate=b;} };
struct ERR_SiteRuntime {struct Group* Group; int InitialGuardCount;};
struct ChimeraAIWorld {
Array<Group*> purged;
static ChimeraAIWorld* Cast(ChimeraAIWorld* p){return p;}
void PurgeSpawnRequestsForGroup(Group* group){
assert(!group->immediate && group->m_aUnitPrefabSlots->empty());
purged.push_back(group);
}
};
struct Game {ChimeraAIWorld* world; ChimeraAIWorld* GetAIWorld(){return world;}};
Game* game;
Game* GetGame(){return game;}
struct Placement { int stops=0; void Stop(){stops++;} };
struct Owner {
std::shared_ptr<Placement> m_ExtractionPlacement;
Array<ERR_SiteRuntime*> m_Sites;
bool m_Stopped=false;
ERR_PrepareResult m_State=ERR_PrepareResult::PENDING;
int routeStops=0;
void StopPatrols(){routeStops++;}
''' + s + '''
};
int main(){
ChimeraAIWorld world; Game instance{&world}; game=&instance;
auto authored=std::make_shared<Array<std::string>>(6,"soldier");
Group empty{true,authored,0}, partial{true,authored,2}, control{true,authored,6}, unrequested{true,authored,0};
ERR_SiteRuntime a{&empty,6},b{&partial,6},c{&control,6},ignored{&unrequested,0},missing{nullptr,6};
Owner owner; owner.m_ExtractionPlacement=std::make_shared<Placement>(); owner.m_Sites={&a,&b,&ignored,&missing};
owner.Stop(); owner.Stop();
assert(owner.m_Stopped && owner.routeStops==1 && world.purged.size()==2 && owner.m_ExtractionPlacement->stops==1);
assert(empty.m_aUnitPrefabSlots->empty() && partial.m_aUnitPrefabSlots->empty());
assert(authored->size()==6 && control.m_aUnitPrefabSlots==authored && unrequested.m_aUnitPrefabSlots==authored);
assert(empty.physical==0 && partial.physical==2 && control.physical==6);
assert(control.immediate && unrequested.immediate);
Owner ready; ready.m_State=ERR_PrepareResult::READY; ready.m_Sites={&c}; ready.Stop();
assert(world.purged.size()==2 && control.immediate && control.m_aUnitPrefabSlots->size()==6);
game=nullptr; Owner deletedGame; deletedGame.m_Sites={&c}; deletedGame.Stop();
assert(world.purged.size()==2);
}
''')
print('PASS: pending-only cancellation retires copied instance intent, preserves physical/control actors, and stops once')
@@ -0,0 +1,321 @@
#!/usr/bin/env python3
"""Exercise process refusal, command scope and evidence gates without native launch."""
from pathlib import Path
import sys
import tempfile
import unittest
from unittest.mock import patch
sys.path.insert(0, str(Path(__file__).resolve().parents[1]/'tools'))
import headless_game as runner
class GameRunnerTests(unittest.TestCase):
def process(self, root, command, comm='wine', pid='123'):
proc = root/pid
proc.mkdir()
(proc/'cmdline').write_bytes(command)
(proc/'comm').write_text(comm)
(proc/'environ').write_bytes(b'')
return proc
def test_refuses_existing_game_variants_without_mutation(self):
for command in (b'Z:/Games/ArmaReforgerSteamDiag.exe\0-world\0x',
b'C:\\Games\\ArmaReforgerSteam.exe\0',
b'proton\0run\0/Z/ArmaReforgerSteamDiag.exe\0'):
with self.subTest(command=command), tempfile.TemporaryDirectory() as directory:
root = Path(directory)
proc = self.process(root, command)
with self.assertRaisesRegex(ValueError, 'game process already exists'):
runner.assert_no_game(root)
self.assertEqual((proc/'cmdline').read_bytes(), command)
def test_truncated_comm_still_refuses_empty_cmdline(self):
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
self.process(root, b'', comm='ArmaReforgerStea')
with self.assertRaisesRegex(ValueError, 'game process already exists'):
runner.assert_no_game(root)
def test_unrelated_workbench_is_not_a_game_process(self):
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
self.process(root, b'Z:/Workbench/ArmaReforgerWorkbenchSteamDiag.exe\0', comm='ArmaReforgerWor')
runner.assert_no_game(root)
def test_unreadable_process_fails_closed(self):
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
self.process(root, b'')
with patch.object(Path, 'read_bytes', side_effect=PermissionError('blocked')):
with self.assertRaisesRegex(ValueError, 'Cannot exclude an existing game'):
runner.assert_no_game(root)
def test_same_prefix_process_refused_other_prefix_preserved(self):
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
compat = root/'compat'
proc = self.process(root, b'wineserver\0')
(proc/'environ').write_bytes(('WINEPREFIX='+str(compat/'pfx')).encode()+b'\0')
with self.assertRaisesRegex(ValueError, 'prefix already has a process'):
runner.assert_prefix_idle(compat, root)
runner.assert_prefix_idle(root/'different', root)
def test_nondumpable_native_service_does_not_require_environment(self):
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
proc = self.process(root, b'/usr/lib/systemd/systemd\0--user\0', comm='systemd')
original = Path.read_bytes
def protected_read(path):
if path.name == 'environ':
self.fail('Unrelated native service environment must not be read')
return original(path)
with patch.object(Path, 'read_bytes', protected_read), patch.object(runner.os, 'readlink', side_effect=PermissionError('non-dumpable')):
runner.assert_prefix_idle(root/'compat', root)
self.assertTrue(proc.exists())
def test_runtime_candidates_require_environment_even_if_exe_is_protected(self):
for command, comm in [(b'/usr/bin/wineserver\0', 'wineserver'),
(b'/usr/bin/python3\0/Steam/Proton - Experimental/proton\0run\0', 'python3'),
(b'/usr/bin/gamescope\0--backend\0headless\0', 'gamescope'),
(b'C:\\windows\\system32\\services.exe\0', 'services.exe')]:
with self.subTest(comm=comm), tempfile.TemporaryDirectory() as directory:
root = Path(directory); self.process(root, command, comm=comm)
original = Path.read_bytes
def protected_read(path):
if path.name == 'environ':
raise PermissionError('protected candidate')
return original(path)
with patch.object(Path, 'read_bytes', protected_read), patch.object(runner.os, 'readlink', side_effect=PermissionError('protected exe')):
with self.assertRaisesRegex(ValueError, 'Cannot verify disposable prefix'):
runner.assert_prefix_idle(root/'compat', root)
def test_unclassifiable_process_remains_fail_closed(self):
with tempfile.TemporaryDirectory() as directory:
root = Path(directory); self.process(root, b'', comm='unknown')
with patch.object(runner.os, 'readlink', side_effect=PermissionError('protected exe')):
with self.assertRaisesRegex(ValueError, 'Cannot classify possible Wine'):
runner.assert_prefix_idle(root/'compat', root)
def test_exact_systemd_pam_helper_is_native_without_environment(self):
with tempfile.TemporaryDirectory() as directory:
root = Path(directory); self.process(root, b'(sd-pam)\0', comm='(sd-pam)')
original = Path.read_bytes
def protected_read(path):
if path.name == 'environ':
self.fail('Native PAM helper environment must not be read')
return original(path)
with patch.object(Path, 'read_bytes', protected_read), patch.object(runner.os, 'readlink', side_effect=PermissionError('non-dumpable')):
runner.assert_prefix_idle(root/'compat', root)
def test_observed_native_apache_signature_is_narrowly_classified(self):
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
proc = self.process(root, b'apache2\0-DFOREGROUND\0', comm='apache2')
with patch.object(runner.os, 'readlink', side_effect=PermissionError('protected exe')):
self.assertFalse(runner.prefix_process_candidate(proc))
(proc/'cmdline').write_bytes(b'apache2\0-DFOREGROUND\0/Steam/proton\0')
self.assertTrue(runner.prefix_process_candidate(proc))
(proc/'cmdline').write_bytes(b'apache2\0')
with self.assertRaisesRegex(ValueError, 'Cannot classify possible Wine'):
runner.prefix_process_candidate(proc)
def test_bare_matching_names_are_not_generically_trusted(self):
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
self.process(root, b'unknown\0', comm='unknown', pid='101')
self.process(root, b'another\0', comm='another', pid='102')
with patch.object(runner.os, 'readlink', side_effect=PermissionError('protected exe')):
with self.assertRaises(ValueError) as raised:
runner.assert_prefix_idle(root/'compat', root)
self.assertIn('101', str(raised.exception))
self.assertIn('102', str(raised.exception)) # report all blockers in one pass
def test_pam_name_does_not_hide_runtime_arguments(self):
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
proc = self.process(root, b'(sd-pam)\0/Steam/proton\0', comm='(sd-pam)')
with patch.object(runner.os, 'readlink', side_effect=PermissionError('protected exe')):
self.assertTrue(runner.prefix_process_candidate(proc))
def test_readonly_inspection_does_not_enter_launcher_or_audio(self):
with patch.object(sys, 'argv', ['headless_game.py', '--compat', '/unused-prefix', '--inspect-processes']):
with patch.object(runner, 'assert_no_game'), patch.object(runner, 'assert_prefix_idle', side_effect=ValueError('ambiguous process')):
with patch.object(runner, 'run') as launch, patch.object(runner.subprocess, 'Popen') as spawn, patch.object(runner.subprocess, 'run') as commands, patch('builtins.print'):
self.assertEqual(runner.main(), 1)
launch.assert_not_called(); spawn.assert_not_called(); commands.assert_not_called()
def test_existing_unmarked_profile_and_steam_prefix_refused(self):
with tempfile.TemporaryDirectory() as directory:
base = Path(directory)
compat = base/'compat'; (compat/'pfx').mkdir(parents=True)
(compat/'pfx/system.reg').touch()
profile = base/'profile'; profile.mkdir(); (profile/'sentinel').write_text('keep')
with self.assertRaisesRegex(ValueError, 'not marked'):
runner.validate_paths(base/'source', base/'steam', compat, profile)
self.assertEqual((profile/'sentinel').read_text(), 'keep')
with self.assertRaisesRegex(ValueError, 'outside Steam'):
runner.validate_paths(base/'source', base, compat, base/'fresh')
def test_profile_cannot_overlap_owned_prefix_or_source(self):
with tempfile.TemporaryDirectory() as directory:
base = Path(directory); compat = base/'compat'
(compat/'pfx').mkdir(parents=True); (compat/'pfx/system.reg').touch()
for profile in (base/'source/profile', compat/'profile', base):
with self.assertRaisesRegex(ValueError, 'separate from source'):
runner.validate_paths(base/'source', base/'steam', compat, profile)
def test_command_is_ordinary_game_with_explicit_successor_identity(self):
for project, guid in [('core', '2528466DE220D91C'), ('chat', 'FA804F411BDDF2C6')]:
command = runner.command_for(runner.ROOT, Path('/Steam'), Path('/compat'), Path('/profile'), project)
self.assertEqual(command[command.index('--')+3], '/Steam/steamapps/common/Arma Reforger/ArmaReforgerSteam.exe')
self.assertFalse(any('ArmaReforger_BE.exe' in arg or 'ArmaReforgerSteamDiag.exe' in arg for arg in command))
self.assertEqual(command[command.index('-addons')+1], guid)
self.assertNotIn('-world', command)
self.assertEqual(command[command.index('-errOrdinaryScenario')+1], project)
for flag in ['-noBackend', '-noSound', '-noSplash', '-noThrow', '-disableCrashReporter']:
self.assertIn(flag, command)
for unwanted in ['-server', '-gproj', '-errPlay', '-errSmoke', '-plugin', 'Workbench', '-silentCrashReport', '-noCrashDialog']:
self.assertFalse(any(unwanted in arg for arg in command))
def test_ready_requires_game_module_without_workbench_and_normal_phase(self):
module = 'SCRIPT : Module: Game; loaded 12x files; defines: "PLATFORM_WINDOWS,ENABLE_DIAG"; CRC32: a\n'
phase = 'SCRIPT : Rereintroduced [mission]: phase 0 -> 1\nSCRIPT : ERR ORDINARY: header verified project=core systems=MissionSystems\nSCRIPT : ERR ORDINARY: local participant verified project=core phase=prison\n'
self.assertTrue(runner.game_evidence(module+phase)['ready'])
self.assertFalse(runner.game_evidence(phase)['ready'])
self.assertFalse(runner.game_evidence(module)['ready'])
self.assertFalse(runner.game_evidence(module.replace('ENABLE_DIAG', 'WORKBENCH')+phase)['ready'])
for error in ['SCRIPT (E): failure', 'RESOURCES (E): missing', 'ERR SMOKE PASS: fixture leaked', 'Rereintroduced: scenario preparation failed']:
self.assertTrue(runner.game_evidence(module+phase+error)['failed'])
def test_startup_requires_selected_header_and_actual_systems_marker(self):
module = 'SCRIPT : Module: Game; defines: "PLATFORM_WINDOWS"; CRC32: a\n'
phase = 'SCRIPT : Rereintroduced [mission]: phase 0 -> 1\n'
core = 'SCRIPT : ERR ORDINARY: header verified project=core systems=MissionSystems\nSCRIPT : ERR ORDINARY: local participant verified project=core phase=prison\n'
chat = 'SCRIPT : ERR ORDINARY: header verified project=chat systems=MissionSystems\nSCRIPT : ERR ORDINARY: local participant verified project=chat phase=prison\n'
self.assertFalse(runner.game_evidence(module+phase, 'core')['ready'])
self.assertFalse(runner.game_evidence(module+phase+core, 'chat')['ready'])
self.assertTrue(runner.game_evidence(module+phase+chat, 'chat')['ready'])
self.assertFalse(runner.game_evidence(module+phase+core.replace('MissionSystems', 'unknown'), 'core')['ready'])
error = "GUI (E): Unknown class 'SCR_WidgetExportRuleRoot'\n"
result = runner.game_evidence(error+module+phase+core, 'core')
self.assertTrue(result['scenario_header_verified'])
self.assertTrue(result['failed'])
self.assertFalse(result['ready'])
def test_world_without_normal_local_admission_is_not_ready(self):
world = ('SCRIPT : Module: Game; defines: "PLATFORM_WINDOWS"; CRC32: a\n'
'SCRIPT : Rereintroduced [mission]: phase 0 -> 1\n'
'SCRIPT : ERR ORDINARY: header verified project=core systems=MissionSystems\n')
result = runner.game_evidence(world, 'core')
self.assertTrue(result['scenario_header_verified'])
self.assertFalse(result['local_participant_verified'])
self.assertFalse(result['ready'])
self.assertFalse(result['failed']) # incomplete admission may still arrive
self.assertFalse(runner.game_evidence(world+'ERR ORDINARY: local participant verified project=chat phase=prison\n', 'core')['ready'])
self.assertTrue(runner.game_evidence(world+'ERR ORDINARY: local participant verified project=core phase=prison\n', 'core')['ready'])
def test_no_engine_or_audio_spawn_during_import_and_process_refusal(self):
with patch.object(runner, 'assert_no_game', side_effect=ValueError('existing game')):
with patch.object(runner.subprocess, 'Popen') as spawn, patch.object(runner.subprocess, 'run') as commands:
class Args:
steam=Path('/steam'); compat=Path('/compat'); profile=Path('/profile')
timeout=180; settle=15; failure_grace=0
with self.assertRaisesRegex(ValueError, 'existing game'):
runner.run(Args())
spawn.assert_not_called(); commands.assert_not_called()
class FailureGraceTests(unittest.TestCase):
def test_exit_at_settle_boundary_is_not_success(self):
monitor = runner.StartupMonitor(100, 180, 5)
self.assertIsNone(monitor.observe({'ready': True}, 101))
self.assertEqual(monitor.observe({'ready': True}, 106, True), 'process-exited')
def test_missing_readiness_resets_continuous_settle(self):
monitor = runner.StartupMonitor(100, 180, 5)
self.assertIsNone(monitor.observe({'ready': True}, 101))
self.assertIsNone(monitor.observe({}, 104))
self.assertIsNone(monitor.observe({'ready': True}, 106))
self.assertEqual(monitor.observe({'ready': True}, 111), 'game-started')
def test_default_error_stops_immediately(self):
monitor = runner.StartupMonitor(100, 180, 15)
self.assertEqual(monitor.observe({'failed': True}, 101), 'game-failed')
self.assertEqual(monitor.first_failure_at, 101)
def test_repeated_errors_do_not_renew_grace(self):
monitor = runner.StartupMonitor(100, 180, 15, 30)
self.assertIsNone(monitor.observe({'failed': True}, 105))
self.assertIsNone(monitor.observe({'failed': True}, 134.99))
self.assertEqual(monitor.first_failure_at, 105)
self.assertEqual(monitor.observe({'failed': True}, 135), 'game-failed')
def test_readiness_cannot_turn_latched_error_into_success(self):
monitor = runner.StartupMonitor(100, 180, 5, 30)
self.assertIsNone(monitor.observe({'failed': True}, 101))
for now in (102, 110, 130):
self.assertIsNone(monitor.observe({'ready': True}, now))
self.assertEqual(monitor.observe({'ready': True}, 131), 'game-failed')
self.assertIsNone(monitor.ready_at)
def test_failure_after_readiness_aborts_settle_success(self):
monitor = runner.StartupMonitor(100, 180, 5, 30)
self.assertIsNone(monitor.observe({'ready': True}, 101))
self.assertIsNone(monitor.observe({'failed': True}, 105))
self.assertIsNone(monitor.observe({'ready': True}, 106))
self.assertEqual(monitor.observe({}, 135), 'game-failed')
def test_absolute_timeout_cuts_short_grace(self):
monitor = runner.StartupMonitor(100, 60, 5, 30)
self.assertIsNone(monitor.observe({'failed': True}, 159))
self.assertEqual(monitor.observe({'ready': True}, 160), 'game-failed')
self.assertEqual(monitor.timeout_result(), 'game-failed')
self.assertEqual(monitor.deadline, 160)
def test_process_exit_during_grace_returns_failed_immediately(self):
monitor = runner.StartupMonitor(100, 180, 15, 30)
monitor.observe({'failed': True}, 101)
self.assertEqual(monitor.observe({}, 102, process_exited=True), 'game-failed')
def test_final_raw_analysis_cannot_erase_observed_failure(self):
monitor = runner.StartupMonitor(100, 180, 15, 30)
monitor.observe({'failed': True}, 101)
final = monitor.annotate({'ready': True, 'failed': False, 'engine_errors': [], 'game_module_observed': True})
self.assertTrue(final['failure_observed_during_polling'])
self.assertTrue(final['failed'])
self.assertFalse(final['ready'])
self.assertEqual(final['engine_errors'], []) # no invented final-log errors
self.assertTrue(final['game_module_observed'])
def test_grace_does_not_delay_normal_success_or_exit(self):
monitor = runner.StartupMonitor(100, 180, 15, 30)
self.assertIsNone(monitor.observe({'ready': True}, 101))
self.assertEqual(monitor.observe({'ready': True}, 116), 'game-started')
monitor = runner.StartupMonitor(100, 180, 15, 30)
self.assertEqual(monitor.observe({}, 101, process_exited=True), 'process-exited')
self.assertEqual(monitor.observe({}, 280), 'timeout')
self.assertEqual(monitor.timeout_result(), 'timeout')
def test_grace_bounds_rejected_before_any_native_mutation(self):
for grace in (-1, 31):
with self.subTest(grace=grace):
with self.assertRaisesRegex(ValueError, 'failure-grace 0..30'):
runner.StartupMonitor(100, 180, 15, grace)
class Args:
steam=Path('/steam'); compat=Path('/compat'); profile=Path('/profile')
timeout=180; settle=15; failure_grace=grace
with patch.object(runner, 'assert_no_game') as processes, patch.object(runner.subprocess, 'Popen') as spawn:
with self.assertRaisesRegex(ValueError, 'failure-grace 0..30'):
runner.run(Args())
processes.assert_not_called(); spawn.assert_not_called()
def test_cli_default_and_explicit_grace(self):
for extra, expected in (([], 0), (['--failure-grace', '30'], 30)):
with self.subTest(extra=extra), patch.object(sys, 'argv', ['headless_game.py', '--compat', '/unused', *extra]):
with patch.object(runner, 'run', return_value=1) as run:
self.assertEqual(runner.main(), 1)
self.assertEqual(run.call_args.args[0].failure_grace, expected)
if __name__ == '__main__':
unittest.main()
@@ -0,0 +1,29 @@
"""Execute initial readiness policy; native population timing needs engine tests."""
from policy_harness import ROOT, body, run
p = ROOT/'addons/core/Scripts/Game/ERR/ERR_InitialGuardRules.c'
s = '\n'.join(body(p, signature) for signature in ('static float TimeoutMilliseconds(', 'static ERR_PrepareResult State(')).replace('ERR_PrepareResult.', 'ERR_PrepareResult::')
run('''#include <cassert>
#include <initializer_list>
enum class ERR_PrepareResult { FAILED=-1,PENDING,READY };
''' + s + '''
int main() {
using R=ERR_PrepareResult;
assert(TimeoutMilliseconds()==90000);
for(int requested: {1,6,12}) {
for(int physical=0;physical<=requested;physical++) {
for(int alive=0;alive<=physical;alive++) {
assert(State(requested,physical,alive,false,false)==R::PENDING);
assert(State(requested,physical,alive,true,false)==((alive==requested)?R::READY:R::PENDING));
assert(State(requested,physical,alive,true,true)==R::FAILED);
assert(State(requested,physical,alive,false,true)==R::FAILED);
}
}
assert(State(requested,requested+1,requested,true,false)==R::FAILED);
}
assert(State(0,0,0,true,false)==R::FAILED);
assert(State(6,2,3,false,false)==R::FAILED);
assert(State(6,-1,0,false,false)==R::FAILED);
assert(State(6,1,-1,false,false)==R::FAILED);
}
''')
print('PASS: requested guard population requires complete physical conscious membership before deadline')
@@ -0,0 +1,78 @@
"""Synthetic identity regression using actual Enforce inventory/count method bodies.
This checks source policy only; it does not simulate native inventory transfers.
"""
import unittest
from policy_harness import ROOT, body, run
def translated(source):
for old, new in [
('InventoryStorageManagerComponent inventory', 'InventoryStorageManagerComponent* inventory'),
('notnull array<IEntity> items', 'Array<Entity*>& items'),
('out array<IEntity> items', 'Array<Entity*>& items'),
('array<IEntity>', 'Array<Entity*>'),
('IEntity item', 'Entity* item'),
('foreach (', 'for ('),
('inventory.GetItems', 'inventory->GetItems'),
('item.GetPrefabData()', 'item->GetPrefabData()'),
('.GetPrefabName()', '->GetPrefabName()'),
('ERR_Inventory.', 'ERR_Inventory::'),
('int count;', 'int count = 0;'),
]:
source = source.replace(old, new)
return source
class InventoryEnumerationPolicy(unittest.TestCase):
def test_duplicate_references_distinct_rounds_and_cross_inventory_union(self):
helper = ROOT / 'addons/core/Scripts/Game/ERR/ERR_Inventory.c'
mortar = ROOT / 'addons/ai/Scripts/Game/ERR/ERR_MortarBattery.c'
methods = '\n'.join(translated(body(helper, signature)) for signature in (
'static int AppendUnique(', 'static int Items('))
count = translated(body(mortar, 'int InventoryShells('))
run(r'''
#include <algorithm>
#include <cassert>
#include <string>
#include <vector>
template <typename T> struct Array : std::vector<T> {
using std::vector<T>::vector;
bool Contains(T v) const { return std::find(this->begin(),this->end(),v)!=this->end(); }
void Insert(T v) { this->push_back(v); }
void Clear() { this->clear(); }
int Count() const { return this->size(); }
};
struct Prefab { std::string name; std::string GetPrefabName() { return name; } };
struct Entity { Prefab* prefab; Prefab* GetPrefabData() { return prefab; } };
struct InventoryStorageManagerComponent {
Array<Entity*> raw;
void GetItems(Array<Entity*>& out) { out = raw; }
};
const std::string SHELL = "mortar-shell";
struct ERR_Inventory {
''' + methods + '\n};\n' + count + r'''
int main() {
Prefab shell{SHELL}, watch{"watch"};
Entity roundA{&shell}, roundB{&shell}, watchA{&watch}, missingPrefab{nullptr};
InventoryStorageManagerComponent one{{&roundA,&roundA,nullptr,&roundB,&watchA,&watchA,&missingPrefab}};
Array<Entity*> unique{&watchA};
assert(ERR_Inventory::Items(&one,unique)==4);
assert(unique[0]==&roundA && unique[1]==&roundB && unique[2]==&watchA && unique[3]==&missingPrefab);
assert(InventoryShells(&one)==2); // Different shells share one prefab, not one identity.
assert(one.raw.size()==7 && one.raw[0]==one.raw[1]); // Enumeration remains untouched.
InventoryStorageManagerComponent two{{&roundB,&roundB,&roundA}};
assert(ERR_Inventory::AppendUnique(&two,unique)==4); // Cross-inventory repeated identities.
assert(ERR_Inventory::AppendUnique(nullptr,unique)==4);
assert(ERR_Inventory::Items(nullptr,unique)==0 && unique.empty());
assert(InventoryShells(nullptr)==0);
InventoryStorageManagerComponent repeated{{&roundA,&roundA,&roundA}};
assert(InventoryShells(&repeated)==1);
InventoryStorageManagerComponent empty{{nullptr,&missingPrefab,&watchA}};
assert(InventoryShells(&empty)==0);
}
''')
if __name__ == '__main__':
unittest.main()
@@ -0,0 +1,89 @@
"""Execute actual resolver/context/latch bodies with opaque native handles.
UUID generation/nullness and native session/controller APIs are substituted;
this is not authentication, native GenV4 or multiplayer evidence.
"""
from policy_harness import ROOT, body, run
import re
source=ROOT/'addons/core/Scripts/Game/ERR/ERR_LocalAdmission.c'
s=source.read_text().split('\nmodded class ERR_GameMode')[0]
s=s[s.index('class ERR_LocalAdmissionRules'):]
s=s.replace('class ERR_LocalAdmissionRules','struct ERR_LocalAdmissionRules').replace('class ERR_LocalAdmission\n','struct ERR_LocalAdmission\n')
s=s.replace('\n}\n','\n};\n').replace('protected ','')
s=s.replace('void ERR_LocalAdmission(', 'ERR_LocalAdmission(')
s=s.replace('ERR_GameMode', 'Mode').replace('SCR_PlayerController', 'Controller').replace('PlayerManager', 'Manager')
s=re.sub(r'\b(Mode|Controller|Manager) (mode|controller|manager|m_Mode|m_Controller)\b',r'\1* \2',s)
s=s.replace('Mode.Get()', 'Mode::Get()').replace('RplMode.None','0')
s=s.replace('Replication.IsServer()', 'isServer').replace('RplSession.Mode()', 'sessionMode')
s=s.replace('GetGame().', 'GetGame()->').replace('manager.', 'manager->').replace('controller.', 'controller->')
s=s.replace('System.GetCLIParam', 'System::GetCLIParam').replace('string project;', 'std::string project;')
s=s.replace('bool connected, sameManager;', 'bool connected=false, sameManager=false;').replace('int controllerId;', 'int controllerId=0;')
s=s.replace('ERR_LocalAdmissionRules.', 'ERR_LocalAdmissionRules::')
s=s.replace('UUID.NULL_UUID','UUID::NULL_UUID').replace('UUID.GenV4()', 'UUID::GenV4()').replace('null','nullptr')
# Enforce initializes managed fields; retain that contract in this C++ model.
s=s.replace('Mode* m_Mode;', 'Mode* m_Mode=nullptr;').replace('Controller* m_Controller;', 'Controller* m_Controller=nullptr;')
s=re.sub(r'\b(bool|int) (m_\w+);',r'\1 \2=0;',s)
run('''#include <cassert>
#include <string>
int generated=0;bool isServer=true;int sessionMode=0;
struct UUID {int value=0;bool IsNull(){return value<=0;}bool operator==(UUID other){return value==other.value;}static UUID NULL_UUID;static UUID GenV4(){return UUID{++generated+100};}};
UUID UUID::NULL_UUID{0};
struct Controller {int id=1;int GetPlayerId(){return id;}};
struct Manager {int count=1;bool connected=true;Controller* controller=nullptr;int GetPlayerCount(){return count;}bool IsPlayerConnected(int id){return connected;}Controller* GetPlayerController(int id){return controller;}};
struct Mode {static Mode* current;static Mode* Get(){return current;}};Mode* Mode::current=nullptr;
struct Game {Manager* manager=nullptr;Controller* local=nullptr;Manager* GetManager(){return manager;}Controller* GetPlayerController(){return local;}};
Game* game=nullptr;Game* GetGame(){return game;}void Print(const char*){}
namespace System {bool GetCLIParam(const char*,std::string&){return false;}}
template<class... Args> void PrintFormat(Args... args) {}
'''+s+'''
int main(){
// Exact None only; every context condition independently matters.
for(int mode=-1;mode<5;++mode)for(int count=0;count<3;++count)for(int flags=0;flags<16;++flags)
assert(ERR_LocalAdmissionRules::Context(flags&1,mode,count,flags&2,flags&4,flags&8,1,1)==(mode==0&&count==1&&flags==15));
assert(!ERR_LocalAdmissionRules::Context(true,0,1,true,true,true,0,0));
assert(!ERR_LocalAdmissionRules::Context(true,0,1,true,true,true,1,2));
Mode round,nextRound;Mode::current=&round;Controller owner,replacement;Manager manager;manager.controller=&owner;Game world{&manager,&owner};game=&world;
ERR_LocalAdmission admission(&round);
UUID selected=admission.Resolve(&round,1,&owner,UUID{0});assert(!selected.IsNull()&&admission.LocalKey()&&generated==1);
assert(admission.Resolve(&round,1,&owner,UUID{0})==selected&&generated==1);
assert(admission.Resolve(&round,1,&owner,UUID{55})==selected&&generated==1); // late BI arrival cannot make fresh life
assert(admission.Validate());
assert(!admission.Disconnected(2));assert(admission.Validate());
assert(admission.Disconnected(1));assert(!admission.Validate());
assert(admission.Resolve(&round,1,&owner,UUID{55}).IsNull()); // irreversible within this mode
ERR_LocalAdmission native(&round);assert(native.Resolve(&round,1,&owner,UUID{55})==UUID{55});
assert(!native.LocalKey()&&native.Resolve(&round,1,&owner,UUID{0})==UUID{55}&&generated==1);
native.Stop();assert(native.Resolve(&round,1,&owner,UUID{0}).IsNull());assert(!native.Validate());
// Replacement, mode switch, manager/local mismatch and additional connections latch.
for(int fault=0;fault<6;++fault){
sessionMode=0;Mode::current=&round;manager.controller=&owner;world.local=&owner;manager.count=1;manager.connected=true;
ERR_LocalAdmission a(&round);assert(!a.Resolve(&round,1,&owner,UUID{0}).IsNull());
if(fault==0)sessionMode=1;
if(fault==1)manager.controller=&replacement;
if(fault==2)world.local=&replacement;
if(fault==3)manager.count=2;
if(fault==4)manager.connected=false;
if(fault==5)Mode::current=&nextRound;
assert(!a.Validate());
sessionMode=0;Mode::current=&round;manager.controller=&owner;world.local=&owner;manager.count=1;manager.connected=true;
assert(!a.Validate());assert(a.Resolve(&round,1,&owner,UUID{88}).IsNull());
}
// A newly created round owns a fresh key. Old resolver cannot be reused.
Mode::current=&nextRound;ERR_LocalAdmission next(&nextRound);UUID nextKey=next.Resolve(&nextRound,1,&owner,UUID{0});assert(!(nextKey==selected));
assert(admission.Resolve(&nextRound,1,&owner,UUID{0}).IsNull());
// Fresh network modes remain native even on an absent controller/local world,
// after Stop, on null backend data, and with changing native identities.
for(int mode: {1,2,3}){
sessionMode=mode;int before=generated;ERR_LocalAdmission network(&nextRound);game=nullptr;
assert(network.Resolve(&nextRound,9,nullptr,UUID{41})==UUID{41});
assert(network.Resolve(&nextRound,9,nullptr,UUID{0}).IsNull());
network.Stop();assert(network.Validate());
assert(network.Resolve(&nextRound,9,nullptr,UUID{42})==UUID{42});
assert(!network.Selected()&&!network.LocalKey()&&generated==before);game=&world;
}
// Incomplete local context cannot generate a key and cannot later self-repair.
sessionMode=0;manager.count=0;int before=generated;ERR_LocalAdmission invalid(&nextRound);
assert(invalid.Resolve(&nextRound,1,&owner,UUID{0}).IsNull()&&generated==before);
manager.count=1;assert(invalid.Resolve(&nextRound,1,&owner,UUID{0}).IsNull());
}
''')
print('PASS: actual local admission context/selection/latch, same-round late identity, replacement/mode failure, fresh round and untouched network path')
@@ -0,0 +1,29 @@
from policy_harness import ROOT,body,run
source=ROOT/'addons/core/Scripts/Game/ERR/ERR_MissionRules.c'
rules='\n'.join(body(source,x) for x in ['static bool Terminal(', 'static bool CanTransition(', 'static bool DefenceComplete(', 'static bool ContactFresh(', 'static int Discovery(']).replace('ERR_Phase.', 'ERR_Phase::')
rules += '\n' + body(ROOT/'addons/core/Scripts/Game/ERR/ERR_PlayerRoster.c', 'static bool CanEnter(').replace('ERR_Phase.', 'ERR_Phase::')
run('''#include <cassert>
namespace ERR_Phase {enum {PREPARING,PRISON,RADIO_SEARCH,RADIO_DEFENCE,EXTRACTION,VICTORY,DEFEAT};}
'''+rules+'''
int main(){
for(int phase=-1;phase<=7;phase++){
assert(!CanEnter(true,phase));
assert(CanEnter(false,phase)==(phase>=1&&phase<=3));
}
for(int from=0;from<=6;from++)for(int to=0;to<=6;to++){
bool expected=(from<5&&to==from+1)||(from>=1&&from<=4&&to==6);
assert(CanTransition(from,to)==expected);
}
assert(!DefenceComplete(100,0,180,true));assert(DefenceComplete(180,0,180,true));
assert(!DefenceComplete(180,0,180,false));assert(!DefenceComplete(300,-1,180,true));
assert(!DefenceComplete(10,20,180,true));assert(!DefenceComplete(300,0,0,true));
assert(ContactFresh(0,120000));assert(!ContactFresh(0,120001));
assert(!ContactFresh(100,99));assert(!ContactFresh(-1,0));
for(int roll=0;roll<100;roll++){
assert(Discovery(0,roll,0)==1);assert(Discovery(0,roll,100)==2);
assert(Discovery(1,roll,0)==2);assert(Discovery(2,roll,0)==2);
assert(Discovery(0,roll,15)==(roll<15?2:1));
}
}
''')
print('PASS: all phase transitions, terminal states, defence boundaries, stale/future observations, intel discovery')
@@ -0,0 +1,101 @@
"""Actual Enforce policies and transaction observation body under narrow API fakes."""
from policy_harness import ROOT, body, run
r=ROOT/'addons/ai/Scripts/Game/ERR'
readiness=r/'ERR_MortarReadiness.c'; transfer=r/'ERR_MortarSupplyTransfer.c'; battery=r/'ERR_MortarBattery.c'
policy='\n'.join([body(readiness,'static ERR_MortarSupplyState Population('),body(readiness,'static bool AllocationValid('),body(readiness,'static int CycleGate('),body(transfer,'static bool Authority('),body(transfer,'static bool Proven(')])
policy=policy.replace('ERR_MortarSupplyState.','ERR_MortarSupplyState::')
run('''#include <cassert>
enum class ERR_MortarSupplyState {FAILED=-1,PENDING,READY};
'''+policy+'''
int main(){
using S=ERR_MortarSupplyState;
assert(Population(0,0,0,false,false)==S::PENDING);
assert(Population(3,3,0,true,false)==S::PENDING);
assert(Population(4,3,1,false,false)==S::PENDING);
assert(Population(4,3,1,true,false)==S::READY);
assert(Population(4,3,1,true,true)==S::FAILED);
assert(Population(0,0,0,false,true)==S::FAILED);
assert(Population(5,3,2,true,false)==S::FAILED);
assert(Population(4,4,0,true,false)==S::FAILED);
assert(AllocationValid(0)&&AllocationValid(9));
assert(!AllocationValid(-1)&&!AllocationValid(10));
assert(Authority(true,false,1,1));
assert(!Authority(false,false,1,1));
assert(!Authority(true,true,1,1));
assert(!Authority(true,false,1,2));
for(int bits=0;bits<16;bits++) {
bool callback=bits&1, source=bits&2, destination=bits&4, exact=bits&8;
assert(Proven(callback,source,destination,exact)==(bits==13));
}
int counter=0;
assert(CycleGate(true,0,counter,8,1)==0); // no physical projectile, no count
for(int i=0;i<1000;i++) if(CycleGate(true,1,counter,8,0)==1) counter++;
assert(counter==0); // pending supply never invokes native super
assert(CycleGate(true,1,counter,8,-1)==-1);
if(CycleGate(true,1,counter,8,1)==1) counter++;
assert(counter==1 && CycleGate(true,1,counter,8,1)==0); // same event not counted twice
assert(CycleGate(false,2,counter,8,1)==-1);
assert(CycleGate(true,8,7,8,-1)==1); // final confirmed round needs no ninth shell
}
''')
# Retain actual control flow; translate only native member/type syntax and the
# component lookup into a directly supplied fake item component.
poll=body(transfer,'ERR_MortarSupplyState Poll(')
poll=poll.replace('ERR_MortarSupplyState.','ERR_MortarSupplyState::').replace('Replication.IsServer()','Replication::IsServer()').replace('InventoryItemComponent item;','InventoryItemComponent* item=nullptr;').replace('if (m_Shell) item = InventoryItemComponent.Cast(m_Shell.FindComponent(InventoryItemComponent));','if (m_Shell) item = m_Shell;').replace('item.GetParentSlot().GetStorage()','item->GetParentSlot()->GetStorage()').replace('item.GetParentSlot()','item->GetParentSlot()')
ack=body(transfer,'void Acknowledge(')
run('''#include <cassert>
enum class ERR_MortarSupplyState {FAILED=-1,PENDING,READY};
struct Replication { static bool IsServer(){return true;} };
struct Slot { void* storage; void* GetStorage(){return storage;} };
struct InventoryItemComponent { Slot* slot; Slot* GetParentSlot(){return slot;} };
'''+body(transfer,'static bool Proven(')+'''
struct Transfer {
bool valid=true,source=true,destination=false,m_Accepted=true,m_Invalidated=false,m_Resolved=false,m_Ready=false;
int m_Source=1,m_Destination=2,m_Acknowledgement=0;
float m_Deadline=8000;
void* m_Storage=this;
Slot slot{this}; InventoryItemComponent item{&slot}; InventoryItemComponent* m_Shell=&item;
bool Valid(float){return valid&&!m_Invalidated;}
bool Contains(int which){return m_Shell && (which==1 ? source : destination);}
'''+ack+poll+'''
};
int main(){
using S=ERR_MortarSupplyState;
Transfer t; assert(t.Poll(0)==S::PENDING && !t.m_Resolved);
t.Acknowledge(true); t.Acknowledge(false); assert(t.m_Acknowledgement==1);
assert(t.Poll(1)==S::PENDING && !t.m_Resolved); // callback alone cannot supply
t.destination=true; assert(t.Poll(2)==S::PENDING); // source still claims ownership
t.source=false; t.slot.storage=nullptr; assert(t.Poll(3)==S::PENDING); // wrong storage
t.slot.storage=t.m_Storage; assert(t.Poll(4)==S::READY && t.m_Resolved);
Transfer stopped; stopped.m_Invalidated=true; stopped.source=false; stopped.destination=true; stopped.Acknowledge(true);
assert(stopped.Poll(5)==S::FAILED && !stopped.m_Ready && stopped.m_Resolved);
Transfer timeout; assert(timeout.Poll(8000)==S::FAILED && !timeout.m_Resolved && timeout.m_Invalidated);
timeout.source=false;timeout.destination=true;timeout.Acknowledge(true);
assert(timeout.Poll(9000)==S::FAILED && timeout.m_Resolved && !timeout.m_Ready); // late success cannot authorize
Transfer late;late.source=false;late.destination=true;late.Acknowledge(true);
assert(late.Poll(8000)==S::FAILED); // no deadline-boundary success bypass
Transfer failed;failed.Acknowledge(false);failed.Acknowledge(true);
assert(failed.Poll(1)==S::FAILED && failed.m_Acknowledgement==-1 && failed.m_Resolved);
Transfer gone;gone.m_Shell=nullptr;gone.Acknowledge(true);
assert(gone.Poll(1)==S::PENDING && !gone.m_Resolved); // ambiguous until deadline, never another move
Transfer unauthorized;unauthorized.valid=false;
assert(unauthorized.Poll(0)==S::FAILED && !unauthorized.m_Resolved);
}
''')
# Source contract checks constrain integration that cannot run without the engine.
b=battery.read_text();sys=(r/'ERR_MortarSystem.c').read_text();f=(r/'ERR_MortarFiring.c').read_text();rd=readiness.read_text();tr=transfer.read_text()
update=body(battery,'void Update(float now)')
assert update.index('m_Readiness.Poll(now)') < update.index('if (!Operational())')
assert 'm_Allocated = true;' in rd and rd.count('TrySpawnPrefabToStorage(ERR_MortarBattery.SHELL')==1
assert rd.index('m_Allocated = true;') < rd.index('TrySpawnPrefabToStorage(ERR_MortarBattery.SHELL')
assert 'm_aUnitPrefabSlots = new array<ResourceName>()' in rd and 'PurgeSpawnRequestsForGroup(group)' in rd
assert 'DeleteSpawned' not in body(readiness,'void Stop(')
assert 'battery.Stop();' in body(r/'ERR_MortarSystem.c','void Stop(')
assert tr.count('TryMoveItemToStorage(')==1 and 'GetItem()' not in tr.replace('callback.GetItem()','')
assert 'm_AttemptedShells.Insert(item)' in b and 'm_AttemptedShells.Contains(item)' in b
assert 'm_Transfer.CapturedOrder() == OrderId' in b
assert 'battery.PendingSupplyReport' in sys and 'supply == ERR_MortarSupplyState.PENDING) return;' in sys
shoot=f[f.index('modded class SCR_AIStaticArtilleryBehavior_ShootingLogic'):]
assert shoot.index('battery.SupplyState(')<shoot.index('super.EOnTaskSimulate(')
assert shoot.count('super.EOnTaskSimulate(')==1 and 'battery.SupplyGunner()' not in shoot
print('PASS: actual startup/generation/ownership/timeout/callback policies and native-counter wait; integration preserves one-shot allocation and pending-crew cancellation')
@@ -0,0 +1,44 @@
"""Exercise the probe's actual native-event evidence gate, not artillery simulation."""
from policy_harness import ROOT, body, run
p=ROOT/'addons/ai/Scripts/Game/ERR/ERR_NativeMortarFiringProbe.c'
s=body(p,'void NativeProjectile(')
s=s.replace('IEntity gun, IEntity projectile','Entity* gun, Entity* projectile')
s=s.replace('m_Battery.', 'm_Battery->').replace('projectile.GetOrigin()', 'projectile->GetOrigin()')
s=s.replace('GetGame().GetWorld().GetWorldTime()', '20000.f')
run('''#include <cassert>
#include <vector>
#include <algorithm>
#include <string>
struct Entity { int GetOrigin(){return 0;} };
struct Battery {bool CommandOpen=true,Released=true;int SourceId=7,OrderId=1;float AimedAt=19000,FlightTime=20;};
struct Items {std::vector<Entity*> values;bool Contains(Entity* p){return std::find(values.begin(),values.end(),p)!=values.end();}void Insert(Entity* p){values.push_back(p);}};
template<class... Args> void PrintFormat(Args... args) {}
struct Probe {
bool m_Stopped=false,m_BadProjectile=false;Battery* m_Battery;Entity* m_Gun;
Items m_Projectiles;int m_Events=0,m_Step=1,m_Source=7;std::string m_BadReason;
'''+s+'''
};
int main(){
Entity gun,other,projectile;Battery battery;
Probe valid;valid.m_Battery=&battery;valid.m_Gun=&gun;
valid.NativeProjectile(&other,&projectile);assert(valid.m_Events==0&&!valid.m_BadProjectile);
valid.NativeProjectile(&gun,&projectile);assert(valid.m_Events==1&&!valid.m_BadProjectile);
valid.NativeProjectile(&gun,&projectile);assert(valid.m_Events==1&&valid.m_BadProjectile);
for(int invalid=0;invalid<8;++invalid){
battery=Battery();Probe p;p.m_Battery=&battery;p.m_Gun=&gun;
if(invalid==0)battery.CommandOpen=false;
if(invalid==1)battery.Released=false;
if(invalid==2)battery.SourceId=8;
if(invalid==3)battery.AimedAt=-1;
if(invalid==4)battery.AimedAt=9999; // older than ten seconds
if(invalid==5)battery.FlightTime=0;
if(invalid==6)p.m_Step=2;
if(invalid==7){p.NativeProjectile(&gun,nullptr);assert(p.m_BadProjectile&&p.m_Events==0);continue;}
p.NativeProjectile(&gun,&projectile);
assert(p.m_Events==1);assert(p.m_BadProjectile);
}
battery=Battery();Probe stopped;stopped.m_Battery=&battery;stopped.m_Gun=&gun;stopped.m_Stopped=true;
stopped.NativeProjectile(&gun,&projectile);assert(stopped.m_Events==0);
}
''')
print('PASS: actual native-event probe gate rejects duplicate/null/wrong-order/uncommitted/un-aimed events; unrelated guns and stopped observers cannot count shots')
@@ -0,0 +1,171 @@
#!/usr/bin/env python3
"""Synthetic comparator regression only; no measured performance evidence."""
import copy
import csv
import importlib.util
import json
from pathlib import Path
import tempfile
import unittest
ROOT = Path(__file__).resolve().parents[1]
spec = importlib.util.spec_from_file_location('compare_performance', ROOT / 'tools/compare_performance.py')
comparison = importlib.util.module_from_spec(spec)
spec.loader.exec_module(comparison)
class PerformanceComparisonTests(unittest.TestCase):
def setUp(self):
self.directory = tempfile.TemporaryDirectory(prefix='erri-synthetic-performance-')
self.addCleanup(self.directory.cleanup)
self.root = Path(self.directory.name)
template = {
'variant': 'baseline', 'repeat_id': 'r1', 'artifact_id': 'synthetic-baseline', 'addon_ids': ['synthetic-base'],
'engine_version': 'synthetic-engine',
'hardware': {'cpu': 'synthetic-cpu', 'gpu': 'synthetic-gpu', 'ram_gib': 32, 'os': 'synthetic-os', 'driver': 'synthetic-driver'},
'workload': {'map': 'synthetic-map', 'route': 'synthetic-route', 'players': 12, 'ai': 36, 'vehicles': 4, 'entities': 100,
'settings': {'resolution': [1920, 1080], 'fps_limit': 0, 'vsync': False}, 'warmup_seconds': 30, 'duration_seconds': 60},
'capture': {'kind': 'client_frame', 'environment': 'client', 'tool': 'synthetic-generator', 'version': '1'},
'sample_file': 'unused.csv',
}
self.data = {'schema_version': 1, 'sample_origin': 'synthetic', 'runs': []}
for repeat in range(1, 4):
for variant, frame in [('baseline', 20), ('successor', 10)]:
run = copy.deepcopy(template)
run.update(variant=variant, repeat_id=f'r{repeat}', artifact_id=f'synthetic-{variant}', sample_file=f'{variant}-{repeat}.csv')
run['addon_ids'] = [f'synthetic-{variant}']
self.data['runs'].append(run)
with (self.root / run['sample_file']).open('w', newline='') as stream:
writer = csv.writer(stream)
writer.writerow(comparison.COLUMNS)
for index in range(1, 90000 // frame + 1):
writer.writerow([index, index * frame, frame, 12, 36, 4, 100, 2])
def execute(self):
manifest = self.root / 'synthetic.json'
manifest.write_text(json.dumps(self.data))
return comparison.compare(manifest)
def change_csv(self, transform):
path = self.root / self.data['runs'][0]['sample_file']
rows = path.read_text().splitlines()
path.write_text('\n'.join(transform(rows)) + '\n')
def replace_frames(self, frames):
path = self.root / self.data['runs'][0]['sample_file']
with path.open('w', newline='') as stream:
writer = csv.writer(stream)
writer.writerow(comparison.COLUMNS)
elapsed = 0
for index, frame in enumerate(frames, 1):
elapsed += frame
writer.writerow([index, elapsed, frame, 12, 36, 4, 100, 2])
def test_paired_arithmetic_is_explicitly_synthetic_and_not_acceptance(self):
report = self.execute()
self.assertEqual(report['sample_origin'], 'synthetic')
self.assertEqual(report['acceptance'], 'not_evaluated')
self.assertEqual(report['aggregate']['baseline']['median_fps'], 50)
self.assertEqual(report['aggregate']['successor']['p99_frame_ms'], 10)
self.assertEqual(report['median_paired_deltas']['median_frame_reduction_percent'], 50)
self.assertEqual(report['runs'][0]['samples_measured'], 3000)
self.assertEqual(len(report['manifest_sha256']), 64)
def test_percentiles_and_warmup_exclusion(self):
self.assertEqual(comparison.percentile(list(range(1, 101)), .99), 99)
self.change_csv(lambda rows: [rows[0]] + [row.rsplit(',', 1)[0] + ',999' if i < 1500 else row for i, row in enumerate(rows[1:])])
self.assertEqual(self.execute()['aggregate']['baseline']['median_ai_simulation_ms'], 2)
def test_rejects_mismatched_conditions(self):
original = copy.deepcopy(self.data)
mutations = [('hardware', 'cpu', 'other'), ('workload', 'ai', 35), ('workload', 'route', 'other'),
('workload', 'settings', {'fps_limit': 30}), ('workload', 'warmup_seconds', 31), ('capture', 'environment', 'workbench_headless')]
for group, key, value in mutations:
with self.subTest(group=group, key=key):
self.data = copy.deepcopy(original)
self.data['runs'][1][group][key] = value
with self.assertRaisesRegex(ValueError, 'mismatched'):
self.execute()
def test_rejects_missing_pair_and_duplicate_repeat(self):
self.data['runs'][-1]['repeat_id'] = 'unpaired'
with self.assertRaisesRegex(ValueError, 'Every repeat'):
self.execute()
self.data['runs'][-1]['repeat_id'] = 'r1'
with self.assertRaisesRegex(ValueError, 'Duplicate repeat'):
self.execute()
def test_rejects_reused_samples(self):
self.data['runs'][1]['sample_file'] = self.data['runs'][0]['sample_file']
with self.assertRaisesRegex(ValueError, 'reused'):
self.execute()
def test_rejects_incomplete_capture(self):
self.change_csv(lambda rows: rows[:-1])
with self.assertRaisesRegex(ValueError, 'incomplete recording'):
self.execute()
def test_rejects_final_stall_hiding_most_of_measurement(self):
# Before the coverage check this 1.2-second sample was accepted as a
# 60-second measurement with 100 FPS, dropping its 60-second stall.
self.replace_frames([20] * 1500 + [10] * 120 + [60000])
with self.assertRaisesRegex(ValueError, 'only 2.000%.*boundary stalls'):
self.execute()
def test_rejects_warmup_crossing_stall_hiding_measurement(self):
# The long frame starts in warm-up and consumes 58.8 measured seconds.
self.replace_frames([20] * 1499 + [58820] + [10] * 120)
with self.assertRaisesRegex(ValueError, 'only 2.000%.*boundary stalls'):
self.execute()
def test_short_boundary_crossings_are_visible_with_high_coverage(self):
self.replace_frames([17] * 5295)
run = self.execute()['runs'][0]
self.assertGreaterEqual(run['measurement_coverage_fraction'], .99)
self.assertLess(run['measurement_coverage_fraction'], 1)
self.assertEqual(len(run['boundary_frames_excluded']), 2)
overlap = sum(frame['measurement_overlap_ms'] for frame in run['boundary_frames_excluded'])
self.assertAlmostEqual(run['measured_frame_seconds'] * 1000 + overlap, 60000)
def test_rejects_coverage_just_below_threshold(self):
self.replace_frames([20] * 1500 + [10] * 5939 + [620])
with self.assertRaisesRegex(ValueError, 'only 98.983%'):
self.execute()
def test_rejects_missing_or_duplicate_frames(self):
self.change_csv(lambda rows: rows[:100] + rows[101:])
with self.assertRaisesRegex(ValueError, 'frame index'):
self.execute()
def test_rejects_population_drift(self):
self.change_csv(lambda rows: rows[:1] + [rows[1].replace(',12,36,', ',12,35,')] + rows[2:])
with self.assertRaisesRegex(ValueError, 'ai workload changed'):
self.execute()
def test_rejects_nonfinite_sample(self):
self.change_csv(lambda rows: rows[:1] + [rows[1].rsplit(',', 1)[0] + ',nan'] + rows[2:])
with self.assertRaisesRegex(ValueError, 'invalid frame/time/load'):
self.execute()
def test_rejects_extra_columns_and_timing_gaps(self):
original = (self.root / self.data['runs'][0]['sample_file']).read_text()
self.change_csv(lambda rows: [rows[0], rows[1] + ',extra'] + rows[2:])
with self.assertRaisesRegex(ValueError, 'columns'):
self.execute()
(self.root / self.data['runs'][0]['sample_file']).write_text(original)
self.change_csv(lambda rows: [rows[0], rows[1].replace('1,20,20,', '1,30,20,')] + rows[2:])
with self.assertRaisesRegex(ValueError, 'elapsed delta'):
self.execute()
def test_rejects_incomplete_metadata_and_infinite_json(self):
del self.data['runs'][0]['capture']['version']
with self.assertRaisesRegex(ValueError, 'expected fields'):
self.execute()
self.data['runs'][0]['capture']['version'] = '1'
self.data['runs'][0]['workload']['settings']['bad'] = float('inf')
with self.assertRaisesRegex(ValueError, 'Non-finite'):
self.execute()
if __name__ == '__main__':
unittest.main()
@@ -0,0 +1,75 @@
"""Execute source-local admission bodies and the reservation rejection predicate.
Only vector arithmetic and opaque UUID equality/nullness are substituted. This is
not a character collision, controller, callback, reconnect or native engine test.
"""
import re
from policy_harness import ROOT, body, run
base = ROOT / 'addons/core/Scripts/Game/ERR'
rules = body(base/'ERR_PlayerRoster.c', 'static bool CanEnter(')
rules += '\n' + body(base/'ERR_SpawnFinalization.c', 'static bool Allows(')
rules += '\n' + body(base/'ERR_SpawnFinalization.c', 'static bool PositionClose(')
rules = rules.replace('ERR_Phase.', 'ERR_Phase::').replace('ERR_PlayerLifeRules.', '')
rules = rules.replace('vector.', 'vector::').replace('Math.', 'Math::')
# Extract the actual condition, rather than maintaining a second implementation.
# Native geometry/terrain branches of Clear are deliberately not emulated.
clear = body(base/'ERR_SpawnPlacement.c', 'bool Clear(')
match = re.search(r'if \((id != ownReservation[^\n]+)\) return false;', clear)
assert match, 'Reservation policy moved: update the source-local extraction'
predicate = match[1].replace('vector.', 'vector::').replace('Math.', 'Math::')
rules += '\nstatic bool ReservationAllows(int id, int ownReservation, vector position, vector reserved) { return !(' + predicate + '); }\n'
run('''#include <cassert>
#include <cmath>
#include <initializer_list>
namespace ERR_Phase {enum {PREPARING,PRISON,RADIO_SEARCH,RADIO_DEFENCE,EXTRACTION,VICTORY,DEFEAT};}
struct UUID {
int identity;
bool IsNull() const { return identity==0; }
bool operator==(UUID other) const { return identity==other.identity; }
};
struct vector {
float x,y,z;
float operator[](int axis) const { return axis==0?x:(axis==1?y:z); }
static float DistanceXZ(vector a, vector b) {return std::hypot(a.x-b.x,a.z-b.z);}
};
namespace Math {static float AbsFloat(float value) {return std::abs(value);}}
''' + rules + '''
int main() {
// Complete independent authorization matrix, including invalid phases and null IDs.
for (int phase=-1;phase<=7;++phase)
for (int flags=0;flags<32;++flags)
for (int oldId=0;oldId<=2;++oldId)
for (int currentId=0;currentId<=2;++currentId) {
bool connected=flags&1,usedLife=flags&2,sameController=flags&4;
bool sameRequest=flags&8,noControlledEntity=flags&16;
bool expected=phase>=1&&phase<=3&&connected&&!usedLife&&oldId>0&&oldId==currentId&&sameController&&sameRequest&&noControlledEntity;
assert(Allows(phase,connected,usedLife,UUID{oldId},UUID{currentId},sameController,sameRequest,noControlledEntity)==expected);
}
const vector origin={0,0,0};
// Inclusive vertical tolerance and just-inside/outside horizontal boundary.
for (float y : {-1.001f,-1.f,-0.2f,0.f,0.2f,1.f,1.001f}) {
assert(PositionClose(vector{0,y,0},origin)==(std::abs(y)<=1));
assert(PositionClose(vector{.599f,y,0},origin)==(std::abs(y)<=1));
assert(!PositionClose(vector{.601f,y,0},origin));
}
assert(PositionClose(vector{.3f,.2f,.3f},origin));
assert(!PositionClose(vector{.5f,0,.5f},origin)); // radial, not independent axis allowance
assert(!PositionClose(vector{0,-20,0},origin)); // fallen below unchanged XZ
assert(!PositionClose(vector{0,20,0},origin)); // displaced above unchanged XZ
// Connection IDs1 and13 must conflict identically; only the caller's own slot is exempt.
for (int id : {1,13,99})
for (int owner : {-1,1,13,99})
for (float x : {-1.201f,-1.199f,0.f,1.199f,1.201f})
for (float y : {-2.001f,-2.f,-1.999f,0.f,1.999f,2.f,2.001f}) {
bool expected=id==owner || std::abs(x)>=1.2 || std::abs(y)>=2;
assert(ReservationAllows(id,owner,origin,vector{x,y,0})==expected);
}
assert(!ReservationAllows(1,13,origin,vector{.8f,0,.8f}));
assert(ReservationAllows(1,13,origin,vector{.9f,0,.9f}));
assert(ReservationAllows(1,13,origin,vector{1.5f,0,0})); // authored grid spacing
// Own reservation is excluded while finalization still checks native geometry separately.
assert(ReservationAllows(13,13,origin,origin));
assert(!ReservationAllows(13,1,origin,origin));
}
''')
print('PASS: player admission phase/life/identity/controller matrix, preload displacement limits, pending reservation overlap and owner exclusion')
@@ -0,0 +1,59 @@
"""Execute the actual prison search body with a recording clearance predicate.
This verifies bounded search order/termination, not terrain or body clearance.
"""
from policy_harness import ROOT,body,run
source=ROOT/'addons/core/Scripts/Game/ERR/ERR_SpawnPlacement.c'
search=(body(source,'bool Prison(').replace('map<int, vector> reservations','map<int, vector>* reservations')
.replace('out vector position','vector& position').replace('ERR_Actors.', 'ERR_Actors::').replace('Math.', 'Math::'))
run('''#include <cassert>
#include <cmath>
#include <vector>
#include <set>
#include <utility>
struct vector {float x,y,z;};
vector operator+(vector a,vector b){return {a.x+b.x,a.y+b.y,a.z+b.z};}
vector Vector(float x,float y,float z){return {x,y,z};}
template<class K,class V> struct map {};
namespace ERR_Actors {vector Ground(vector value){return value;}}
namespace Math {int AbsInt(int value){return std::abs(value);}}
struct Search {
std::vector<vector> visited;
int accept=-1;
bool Clear(vector candidate,map<int,vector>*){visited.push_back(candidate);return int(visited.size())-1==accept;}
''' + search + '''
};
int main(){
const vector center={6090,100,7160};
vector result={-1,-1,-1};
Search blocked;
assert(!blocked.Prison(center,nullptr,result));
assert(blocked.visited.size()==16);
assert(result.x==-1&&result.y==-1&&result.z==-1); // no outside fallback
std::set<std::pair<float,float>> unique;
for(int i=0;i<16;++i){
vector candidate=blocked.visited[i];
float x=candidate.x-center.x,z=candidate.z-center.z;
assert(std::abs(x)<=4.5f&&std::abs(z)<=4.5f);
assert(unique.insert({x,z}).second);
assert(std::abs(x)==1.5f||std::abs(x)==4.5f);
assert(std::abs(z)==1.5f||std::abs(z)==4.5f);
int outer=(std::abs(x)==4.5f)+(std::abs(z)==4.5f);
assert(outer==(i<4?0:(i<12?1:2)));
if(i<12)assert(std::hypot(x,z)<5); // inner and edge spawns meet prior 5m check
for(int j=0;j<i;++j){
vector previous=blocked.visited[j];
assert(std::hypot(candidate.x-previous.x,candidate.z-previous.z)>=3);
}
}
// Select any first available position; never bypass the native clearance predicate.
for(int accepted=0;accepted<16;++accepted){
Search search;search.accept=accepted;
assert(search.Prison(center,nullptr,result));
assert(search.visited.size()==unsigned(accepted+1));
vector expected=blocked.visited[accepted];
assert(result.x==expected.x&&result.y==expected.y&&result.z==expected.z);
}
}
''')
print('PASS: prison search packs 16 unique 3m-spaced inside-wall centers, prioritizes inner/edge positions and never bypasses clearance')
@@ -0,0 +1,44 @@
"""Exercise actual radio tuning, defender and continuity policy bodies.
Native fixture covers service events and physical character state separately.
"""
from policy_harness import ROOT, body, run
source=ROOT/'addons/core/Scripts/Game/ERR/ERR_RadioDefenceService.c'
functions='\n'.join(body(source, signature) for signature in (
'static float DefenceRadius(', 'static float TuneRadius(',
'static bool CanTune(', 'static bool Defender(', 'static float SinceAfterSample(',
)).replace('ERR_Phase.', 'ERR_Phase::')
functions+='\n'+body(ROOT/'addons/core/Scripts/Game/ERR/ERR_MissionRules.c','static bool DefenceComplete(')
run('''#include <cassert>
#include <initializer_list>
namespace ERR_Phase {enum {PREPARING,PRISON,RADIO_SEARCH,RADIO_DEFENCE,EXTRACTION,VICTORY,DEFEAT};}
'''+functions+'''
int main() {
for (int phase=-1;phase<=7;++phase)
for (int flags=0;flags<16;++flags)
for (int knowledge=0;knowledge<=2;++knowledge)
for (float distance : {-1.f,0.f,4.999f,5.f,5.001f,60.f}) {
bool registered=flags&1,radio=flags&2,player=flags&4,conscious=flags&8;
bool expected=phase==ERR_Phase::RADIO_SEARCH && registered && radio && knowledge>=2 && player && conscious && distance>=0 && distance<=5;
assert(CanTune(phase,registered,radio,knowledge,player,conscious,distance)==expected);
}
for (int flags=0;flags<4;++flags)
for (float distance : {-1.f,0.f,59.999f,60.f,60.001f})
assert(Defender(flags&1,flags&2,distance)==(bool(flags&1)&&bool(flags&2)&&distance>=0&&distance<60));
assert(DefenceRadius()==60 && TuneRadius()==5);
float since=SinceAfterSample(-1,-1,1000,2);
assert(since==1000);
since=SinceAfterSample(since,1000,6000,1);
assert(since==1000); // second person can leave without resetting remaining defender
since=SinceAfterSample(since,6000,7000,0);
assert(since==-1); // absent/dead/unconscious/empty-server samples reset
since=SinceAfterSample(since,7000,8000,1);
assert(since==8000);
assert(!DefenceComplete(37999,since,30000,true));
assert(DefenceComplete(38000,since,30000,true));
assert(!DefenceComplete(38000,since,45000,true)); // live setting increased
assert(SinceAfterSample(since,38000,30000,1)==30000); // backward clock resets interval
assert(SinceAfterSample(since,38000,-1,1)==-1);
assert(SinceAfterSample(since,38000,50000,-1)==-1);
}
''')
print('PASS: radio authorization/discovery/phase matrix, exact distance limits, defender handover, interruption, empty samples, clock regression and duration boundary')
@@ -0,0 +1,36 @@
"""Execute the production presentation-state policy; no network claim."""
from policy_harness import ROOT, body, run
source=ROOT/'addons/core/Scripts/Game/ERR/ERR_RadioFeedback.c'
function=body(source,'static ERR_RadioFeedback Next(').replace('ERR_RadioFeedback.', 'ERR_RadioFeedback::')
run('''#include <cassert>
enum class ERR_RadioFeedback {INACTIVE, WAITING, TRANSMITTING, INTERRUPTED};
'''+function+'''
int main() {
using S=ERR_RadioFeedback;
const S emptyExpected[]={S::WAITING,S::WAITING,S::INTERRUPTED,S::INTERRUPTED};
for (int previous=0;previous<4;++previous) {
S state=static_cast<S>(previous);
// Terminal/new-round state always clears; stale occupancy cannot resurrect it.
assert(Next(state,false,false)==S::INACTIVE);
assert(Next(state,false,true)==S::INACTIVE);
assert(Next(state,true,true)==S::TRANSMITTING);
assert(Next(state,true,false)==emptyExpected[previous]);
}
S state=Next(S::INACTIVE,true,false);
assert(state==S::WAITING);
for (int sample=0;sample<100;++sample) state=Next(state,true,false);
assert(state==S::WAITING); // initial wait is not an interruption
state=Next(state,true,true);
assert(state==S::TRANSMITTING);
state=Next(state,true,false);
assert(state==S::INTERRUPTED);
for (int sample=0;sample<100;++sample) state=Next(state,true,false);
assert(state==S::INTERRUPTED); // do not alternate guide messages while empty
state=Next(state,true,true);
assert(state==S::TRANSMITTING);
state=Next(state,false,true);
assert(state==S::INACTIVE);
assert(Next(state,true,false)==S::WAITING); // fresh round has no stale interruption
}
''')
print('PASS: actual radio feedback policy, initial wait, interruption persistence, resumption and terminal/new-round reset')
@@ -0,0 +1,17 @@
from policy_harness import ROOT, body, run
p = ROOT / 'addons/core/Scripts/Game/ERR/ERR_RecoveryService.c'
rules = body(p, 'static int SurvivorKind(') + '\n' + body(p, 'static bool NeedsRescuer(')
run('''#include <cassert>
''' + rules + '''
int main() {
for (int flags=0;flags<16;flags++) {
bool alive=flags&1, connected=flags&2, same=flags&4, conscious=flags&8;
int expected=!alive?0:(!connected||!same)?1:conscious?2:3;
assert(SurvivorKind(alive,connected,same,conscious)==expected);
}
for (int conscious=0;conscious<=12;conscious++)
for (int incapacitated=0;incapacitated<=12;incapacitated++)
assert(NeedsRescuer(conscious,incapacitated)==(conscious==0&&incapacitated>0));
}
''')
print('PASS: recovery state excludes dead bodies, preserves reservations, requires controlled rescuers and distinguishes empty/all-dead teams')
@@ -0,0 +1,409 @@
"""Release-gate bypass regressions. Synthetic evidence is confined to temp dirs."""
from pathlib import Path
import copy
import hashlib
import json
import shutil
import subprocess
import sys
import tempfile
import unittest
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT / 'tools'))
import release_check as gate
from native_report import analyze
from source_manifest import addon_manifest
from native_provenance import snapshot, bindings, persist, seal_run, archive_source, qualify_archive, MANIFEST, METADATA, PROVENANCE
class ReleaseAuditTests(unittest.TestCase):
def setUp(self):
self.temp = tempfile.TemporaryDirectory(prefix='erri-release-test-')
self.addCleanup(self.temp.cleanup)
self.root = Path(self.temp.name)
self.write('addons/core/addon.gproj', 'Project {}')
self.write('addons/core/Scripts/Game/Test.c', 'class Test {}')
self.write('addons/core/Assets/test.png', b'nonempty resource bytes')
self.write('docs/evidence/current/manual.txt', 'Synthetic test fixture, not real acceptance.\n')
self.log = 'docs/evidence/current/console.log.txt'
self.report = 'docs/evidence/current/report.json'
self.manifest = 'docs/evidence/current/source-sha256.json'
self.write(self.log, 'ERR SMOKE PASS: synthetic\nERR SMOKE COMPLETE: synthetic\n')
self.refresh_native()
ordinary = {'status': 'passed', 'evidence': ['docs/evidence/current/manual.txt']}
native = {'status': 'passed', 'evidence': [self.report, self.manifest],
'source_manifest': self.manifest, 'native_report': self.report}
self.ledger = {'target': 'Everon, vanilla factions, 12 players',
'cases': {name: copy.deepcopy(ordinary) for name in gate.REQUIRED_CASES},
'development_checks': {'clean_native_runtime': copy.deepcopy(native)}}
self.ledger['cases']['independent_native_build'] = copy.deepcopy(native)
def write(self, relative, value):
path = self.root / relative
path.parent.mkdir(parents=True, exist_ok=True)
path.write_bytes(value if isinstance(value, bytes) else value.encode())
def json(self, relative, value):
self.write(relative, json.dumps(value))
def refresh_native(self):
captured = snapshot(self.root, ['synthetic-runner-not-an-engine'])
archive = Path(self.manifest).parent
self.write(self.manifest, captured[0])
self.write(str(archive / MANIFEST), captured[0])
self.write(str(archive / METADATA), captured[1])
self.json(str(archive / PROVENANCE), {'schema_version': 1, 'kind': 'launch_snapshot'})
self.json(str(archive / 'runner.json.txt'), {**bindings(captured), 'started_unix': json.loads(captured[1])['captured_unix'] + 1, 'result': 'smoke-completed', 'rounds_required': 1, 'stopped_unix': json.loads(captured[1])['captured_unix'] + 2, 'source_unchanged_after_run': True, 'end_source_sha256': hashlib.sha256(captured[0]).hexdigest(), 'console_sha256': hashlib.sha256((self.root / self.log).read_bytes()).hexdigest()})
self.json(self.report, analyze((self.root / self.log).read_text(), self.log))
def run_audit(self):
self.json('docs/acceptance.json', self.ledger)
return gate.audit(self.root)
def blocked(self, fragment):
errors = self.run_audit()
self.assertTrue(errors, 'malformed evidence incorrectly qualified')
self.assertTrue(any(fragment in error for error in errors), errors)
def test_complete_synthetic_fixture_qualifies(self):
self.assertEqual(self.run_audit(), [])
def test_failed_clean_runtime_blocks_even_when_all_cases_pass(self):
self.ledger['development_checks']['clean_native_runtime']['status'] = 'failed'
self.blocked('clean_native_runtime: status is failed')
def test_every_required_case_is_mandatory(self):
for name in gate.REQUIRED_CASES:
with self.subTest(name=name):
saved = self.ledger['cases'].pop(name)
self.blocked(name + ': required first-release case is missing')
self.ledger['cases'][name] = saved
def test_unknown_case_rejected(self):
self.ledger['cases']['fake_replacement'] = {'status': 'passed', 'evidence': [self.log]}
self.blocked('unknown first-release case')
def test_missing_runtime_gate_rejected(self):
self.ledger['development_checks'].clear()
self.blocked('required clean-runtime gate is missing')
def test_unknown_and_malformed_statuses_rejected_everywhere(self):
entry = self.ledger['cases']['escape_loop']
for status in ('PASS', 'waived', '', None, True, {}, []):
with self.subTest(status=status):
entry['status'] = status
self.blocked('unknown or malformed status')
entry['status'] = 'passed'
self.ledger['development_checks']['historical'] = {'status': 'waived', 'evidence': []}
self.blocked('unknown or malformed status')
def test_malformed_sections_entries_and_evidence(self):
original = copy.deepcopy(self.ledger)
for section in ('cases', 'development_checks'):
self.ledger = copy.deepcopy(original)
self.ledger[section] = []
self.blocked(section + ' must be an object')
for entry in (None, [], 'passed'):
self.ledger = copy.deepcopy(original)
self.ledger['cases']['escape_loop'] = entry
self.blocked('entry must be an object')
for evidence in (None, self.log, {}, [None], [42]):
self.ledger = copy.deepcopy(original)
self.ledger['cases']['escape_loop']['evidence'] = evidence
self.blocked('evidence')
def test_passed_requires_nonempty_evidence(self):
self.ledger['cases']['escape_loop']['evidence'] = []
self.blocked('requires nonempty evidence')
def test_empty_files_and_whitespace_cannot_qualify(self):
for value in (b'', b' \r\n\t'):
self.write('docs/evidence/empty.txt', value)
self.ledger['cases']['escape_loop']['evidence'] = ['docs/evidence/empty.txt']
self.blocked('evidence is empty')
def test_missing_and_directory_evidence_rejected(self):
for path in ('docs/evidence/missing.txt', 'docs/evidence/current'):
self.ledger['cases']['escape_loop']['evidence'] = [path]
self.blocked('not an existing regular file')
def test_unsafe_paths_rejected(self):
for path in ('/etc/passwd', '../outside', 'docs/../docs/evidence/current/manual.txt',
'./docs/evidence/current/manual.txt', 'docs//evidence/current/manual.txt',
'C:\\evidence.txt', '.git/config', 'docs/evidence/\x00invalid'):
with self.subTest(path=path):
self.ledger['cases']['escape_loop']['evidence'] = [path]
self.assertTrue(self.run_audit())
def test_symlinks_even_inside_repository_rejected(self):
for target in (self.root / self.log, Path('/etc/passwd')):
link = self.root / 'docs/evidence/link.txt'
link.symlink_to(target)
self.ledger['cases']['escape_loop']['evidence'] = ['docs/evidence/link.txt']
self.assertTrue(self.run_audit())
link.unlink()
def test_symlink_loop_returns_error_without_crash(self):
link = self.root / 'docs/evidence/loop'
link.symlink_to(link)
self.ledger['cases']['escape_loop']['evidence'] = ['docs/evidence/loop']
self.assertTrue(self.run_audit())
def test_duplicate_paths_rejected(self):
self.ledger['cases']['escape_loop']['evidence'] = [self.log, self.log]
self.blocked('duplicate evidence path')
def test_missing_explicit_native_fields_rejected(self):
for field in ('source_manifest', 'native_report'):
value = self.ledger['cases']['independent_native_build'].pop(field)
self.blocked('independent_native_build.' + field)
self.ledger['cases']['independent_native_build'][field] = value
def test_explicit_native_fields_must_be_listed_as_evidence(self):
self.ledger['cases']['independent_native_build']['evidence'] = [self.log]
self.blocked('must also appear')
def test_current_native_qualification_rejects_changed_added_deleted_files(self):
path = self.root / 'addons/core/Scripts/Game/Test.c'
original = path.read_bytes()
path.write_text('class Changed {}')
self.blocked('changed=1')
path.write_bytes(original)
added = self.root / 'addons/core/Assets/new.custom-resource'
added.write_bytes(b'resource')
self.blocked('missing=1')
added.unlink()
path.unlink()
self.blocked('extra=1')
def test_clean_runtime_also_requires_current_manifest(self):
self.ledger['cases']['independent_native_build']['status'] = 'pending'
self.write('addons/core/Scripts/Game/Test.c', 'class Changed {}')
self.blocked('clean_native_runtime.source_manifest: manifest does not match')
def test_incomplete_and_malformed_manifest_rejected(self):
for manifest in ({}, [], {'addons/core/addon.gproj': 'not-sha256'}):
self.json(self.manifest, manifest)
self.blocked('manifest must be a nonempty')
self.json(self.manifest, {'addons/core/addon.gproj': '0' * 64})
self.blocked('manifest does not match')
def test_native_report_cannot_hide_raw_errors(self):
self.write(self.log, 'ERR SMOKE PASS: synthetic\nWORLD (E): retained error\nERR SMOKE COMPLETE: synthetic\n')
self.blocked('does not match analysis')
self.refresh_native()
self.blocked('no script, engine or end-screen errors')
def test_each_native_failure_category_blocks(self):
for failure in ('ERR SMOKE FAIL: assertion', 'Virtual Machine Exception',
'SCRIPT (E): exception', 'ANIMATION (E): unknown resource', 'ENGINE (F): Crashed', 'Could not find expected endscreen',
"entity won't take damage and wont replicate"):
self.write(self.log, 'ERR SMOKE PASS: test\n' + failure + '\nERR SMOKE COMPLETE: test\n')
self.refresh_native()
self.blocked('native raw log must contain')
def test_truncated_and_assertion_free_logs_rejected(self):
for text in ('ERR SMOKE PASS: test\n', 'ERR SMOKE COMPLETE: test\n', 'unrelated log\n'):
self.write(self.log, text)
self.refresh_native()
self.blocked('successful completion/assertions')
def test_native_report_types_and_missing_fields_rejected(self):
report = analyze((self.root / self.log).read_text(), self.log)
for bad in ({}, [], dict(report, smoke_completions=True), dict(report, engine_errors='')):
self.json(self.report, bad)
self.blocked('native_report')
def test_native_artifacts_cannot_be_mixed_between_archives(self):
self.write('docs/evidence/other/source-sha256.json', (self.root / self.manifest).read_bytes())
entry = self.ledger['cases']['independent_native_build']
entry['source_manifest'] = 'docs/evidence/other/source-sha256.json'
entry['evidence'].append(entry['source_manifest'])
self.blocked('same evidence archive')
def test_historical_development_manifests_need_not_match_current(self):
self.json('docs/evidence/historical/source-sha256.json', {'old/path.c': '0' * 64})
self.ledger['development_checks']['historical'] = {
'status': 'passed', 'evidence': ['docs/evidence/historical/source-sha256.json']}
self.ledger['development_checks']['expected_fault'] = {'status': 'failed', 'evidence': []}
self.assertEqual(self.run_audit(), [])
def test_generated_state_excluded_but_new_resource_formats_included(self):
self.write('addons/core/resourceDatabase.rdb', 'generated')
self.write('addons/core/resources.pak', 'generated')
self.write('addons/core/profiles/runtime.json', 'generated')
self.assertEqual(self.run_audit(), [])
self.write('addons/core/Scripts/Game/resourceDatabase.rdb_fake.c', 'class New {}')
self.blocked('missing=1')
def test_source_symlink_cannot_hide_from_manifest(self):
(self.root / 'addons/core/Scripts/Game/Alias.c').symlink_to(self.root / 'addons/core/Scripts/Game/Test.c')
self.blocked('source/resource symlink is not supported')
def test_duplicate_json_keys_and_invalid_json_fail_closed(self):
for raw in ('{"cases":{},"cases":{}}', '{', '[]', '{"target":NaN}'):
self.write('docs/acceptance.json', raw)
self.assertTrue(gate.audit(self.root))
def test_symlinked_ledger_rejected(self):
self.json('docs/real-ledger.json', self.ledger)
(self.root / 'docs/acceptance.json').symlink_to(self.root / 'docs/real-ledger.json')
self.assertTrue(gate.audit(self.root))
def test_checker_is_read_only(self):
self.json('docs/acceptance.json', self.ledger)
before = {str(path.relative_to(self.root)): path.read_bytes()
for path in self.root.rglob('*') if path.is_file()}
self.assertEqual(gate.audit(self.root), [])
after = {str(path.relative_to(self.root)): path.read_bytes()
for path in self.root.rglob('*') if path.is_file()}
self.assertEqual(after, before)
def test_archive_command_uses_shared_manifest_and_report(self):
tools = self.root / 'tools'
tools.mkdir()
for name in ('archive_native.py', 'native_report.py', 'source_manifest.py', 'native_provenance.py'):
shutil.copyfile(ROOT / 'tools' / name, tools / name)
session = self.root / 'synthetic-session'
session.mkdir()
(session / 'console.log').write_text((self.root / self.log).read_text())
archive = self.root / Path(self.manifest).parent
for name in (MANIFEST, METADATA):
shutil.copyfile(archive / name, session / name)
shutil.copyfile(archive / 'runner.json.txt', session / 'runner.json')
subprocess.run([sys.executable, str(tools / 'archive_native.py'), str(session), 'new-archive'],
capture_output=True, text=True, check=True)
archive = self.root / 'docs/evidence/new-archive'
self.assertEqual(json.loads((archive / 'source-sha256.json').read_text()), addon_manifest(self.root))
report = json.loads((archive / 'report.json').read_text())
self.assertEqual(report, analyze((self.root / report['log']).read_text(), report['log']))
def test_native_report_command_compatibility(self):
result = subprocess.run([sys.executable, str(ROOT / 'tools/native_report.py'), str(self.root / self.log)],
capture_output=True, text=True, check=True)
self.assertEqual(json.loads(result.stdout), analyze((self.root / self.log).read_text(), self.root / self.log))
def test_archive_time_provenance_cannot_qualify_native_gates(self):
self.json('docs/evidence/current/' + PROVENANCE, {'schema_version': 1, 'kind': 'archive_time_only'})
self.blocked('requires launch_snapshot provenance')
def test_missing_launch_snapshot_is_not_current_evidence(self):
(self.root / 'docs/evidence/current' / METADATA).unlink()
self.blocked('launch_provenance')
def test_modified_launch_bytes_and_runner_binding_rejected(self):
path = self.root / 'docs/evidence/current' / MANIFEST
path.write_bytes(path.read_bytes() + b'\n')
self.blocked('launch manifest byte hash')
self.refresh_native()
runner = self.root / 'docs/evidence/current/runner.json.txt'
data = json.loads(runner.read_text())
data['launch_id'] = '00000000-0000-0000-0000-000000000000'
runner.write_text(json.dumps(data))
self.blocked('runner launch binding')
def test_snapshot_after_process_start_rejected(self):
runner = self.root / 'docs/evidence/current/runner.json.txt'
data = json.loads(runner.read_text())
data['started_unix'] = 1
runner.write_text(json.dumps(data))
self.blocked('snapshot must precede process launch')
def test_runner_failure_and_incomplete_repeated_rounds_cannot_qualify(self):
runner = self.root / 'docs/evidence/current/runner.json.txt'
data = json.loads(runner.read_text())
data['result'] = 'process-exited'
runner.write_text(json.dumps(data))
self.blocked('completed runner session')
data['result'] = 'smoke-completed'
data['rounds_required'] = 2
runner.write_text(json.dumps(data))
self.blocked('successful completion/assertions')
def test_prelaunch_snapshot_remains_old_when_persisted_after_edit(self):
captured = snapshot(self.root, ['synthetic'])
self.write('addons/core/Scripts/Game/Test.c', 'class ChangedAfterLaunch {}')
session = self.root / 'synthetic-late-session'
session.mkdir()
persist(session, captured)
self.assertEqual((session / MANIFEST).read_bytes(), captured[0])
(session / 'console.log').write_text('Synthetic old run')
self.json('synthetic-late-session/runner.json', {**bindings(captured), 'started_unix': json.loads(captured[1])['captured_unix'] + 1, 'stopped_unix': json.loads(captured[1])['captured_unix'] + 2, 'source_unchanged_after_run': True, 'end_source_sha256': hashlib.sha256(captured[0]).hexdigest(), 'console_sha256': hashlib.sha256((session / 'console.log').read_bytes()).hexdigest()})
with self.assertRaisesRegex(ValueError, 'differ from pre-launch snapshot'):
archive_source(session, self.root)
def test_legacy_archive_requires_opt_in_and_is_marked_historical(self):
session = self.root / 'synthetic-legacy'
session.mkdir()
with self.assertRaisesRegex(ValueError, 'no pre-launch source snapshot'):
archive_source(session, self.root)
manifest, provenance, launched = archive_source(session, self.root, allow_legacy=True)
self.assertFalse(launched)
self.assertEqual(provenance['kind'], 'archive_time_only')
self.assertEqual(provenance['qualification'], 'historical_only')
self.assertEqual(json.loads(manifest), addon_manifest(self.root))
def test_partial_launch_evidence_cannot_fall_back_to_legacy(self):
session = self.root / 'synthetic-partial'
session.mkdir()
(session / METADATA).write_text('{}')
with self.assertRaisesRegex(ValueError, 'missing or symlinked launch evidence'):
archive_source(session, self.root, allow_legacy=True)
def test_source_manifest_copy_must_match_exact_launch_bytes(self):
path = self.root / self.manifest
path.write_bytes(path.read_bytes() + b'\n')
self.blocked('differs from exact launch snapshot bytes')
def test_recomputed_report_cannot_relabel_a_different_old_raw_log(self):
self.write(self.log, 'ERR SMOKE PASS: different synthetic run\nERR SMOKE COMPLETE: other\n')
self.json(self.report, analyze((self.root / self.log).read_text(), self.log))
self.blocked('raw native log differs from stopped runner log hash')
def test_report_cannot_use_an_unsealed_neighbor_log(self):
other = 'docs/evidence/current/other.log.txt'
self.write(other, 'ERR SMOKE PASS: unrelated\nERR SMOKE COMPLETE: unrelated\n')
self.json(self.report, analyze((self.root / other).read_text(), other))
self.blocked('exact console.log.txt sealed by the stopped runner')
def test_stopped_source_change_blocks_even_if_current_files_match_launch(self):
runner = self.root / 'docs/evidence/current/runner.json.txt'
data = json.loads(runner.read_text())
data['source_unchanged_after_run'] = False
data['end_source_sha256'] = '0' * 64
runner.write_text(json.dumps(data))
self.blocked('changed between launch and stopped-run snapshot')
def test_seal_uses_stopped_sources_and_exact_log_bytes(self):
session = self.root / 'synthetic-seal'
session.mkdir()
captured = snapshot(self.root, ['synthetic'])
(session / 'console.log').write_bytes(b'exact synthetic log\r\n')
sealed = seal_run(self.root, session, captured)
self.assertTrue(sealed['source_unchanged_after_run'])
self.assertEqual(sealed['console_sha256'], hashlib.sha256(b'exact synthetic log\r\n').hexdigest())
self.write('addons/core/Scripts/Game/Test.c', 'class ChangedDuringRun {}')
self.assertFalse(seal_run(self.root, session, captured)['source_unchanged_after_run'])
def test_archive_cli_requires_explicit_legacy_import(self):
tools = self.root / 'tools'
tools.mkdir()
for name in ('archive_native.py', 'native_report.py', 'source_manifest.py', 'native_provenance.py'):
shutil.copyfile(ROOT / 'tools' / name, tools / name)
session = self.root / 'synthetic-legacy-command'
session.mkdir()
(session / 'console.log').write_text((self.root / self.log).read_text())
command = [sys.executable, str(tools / 'archive_native.py'), str(session), 'legacy-archive']
rejected = subprocess.run(command, capture_output=True, text=True)
self.assertEqual(rejected.returncode, 2)
self.assertFalse((self.root / 'docs/evidence/legacy-archive').exists())
subprocess.run(command + ['--allow-legacy-archive-time-source'], capture_output=True, text=True, check=True)
provenance = json.loads((self.root / 'docs/evidence/legacy-archive' / PROVENANCE).read_text())
self.assertEqual(provenance['kind'], 'archive_time_only')
with self.assertRaisesRegex(ValueError, 'requires launch_snapshot provenance'):
qualify_archive(self.root / 'docs/evidence/legacy-archive', addon_manifest(self.root))
if __name__ == '__main__':
unittest.main()
@@ -0,0 +1,31 @@
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)
assert deferred==['ai:convoyCount']
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 <cassert>\n#include <string>\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')
@@ -0,0 +1,25 @@
"""Execute production discovery bounds; native LOS/identity remain runtime checks."""
from policy_harness import ROOT, body, run
source = ROOT / 'addons/core/Scripts/Game/ERR/ERR_SiteDiscoveryRules.c'
methods = '\n'.join(body(source, sig) for sig in (
'static float RadioRadiusLimit(', 'static bool ValidRadius(', 'static bool InRange('
)).replace('ERR_LocationKind.', 'ERR_LocationKind::')
run('''#include <cassert>
enum class ERR_LocationKind { PRISON, RADIO, EXTRACTION, OUTPOST, DEPOT };
''' + methods.replace('int kind,', 'ERR_LocationKind kind,') + '''
int main() {
using K=ERR_LocationKind;
assert(ValidRadius(K::RADIO,0) && ValidRadius(K::RADIO,8));
assert(!ValidRadius(K::RADIO,8.01f) && !ValidRadius(K::RADIO,-1));
assert(ValidRadius(K::DEPOT,60) && ValidRadius(K::OUTPOST,60));
assert(!ValidRadius(K::DEPOT,60.01f));
assert(ValidRadius(K::PRISON,0) && ValidRadius(K::EXTRACTION,0));
assert(!ValidRadius(K::PRISON,1) && !ValidRadius(K::EXTRACTION,1));
assert(!ValidRadius(static_cast<K>(42),0));
assert(InRange(8,8,8) && InRange(8,0,0));
assert(!InRange(0,0,0) && !InRange(8,8.01f,0));
assert(!InRange(8,0,8.01f) && !InRange(8,-1,0) && !InRange(8,0,-1));
}
''')
print('PASS: authored radio/optional-site bounds and physical horizontal/vertical boundaries')
@@ -0,0 +1,50 @@
"""Run actual clock parsing/formatting and progression policy bodies as C++.
Native world authority, JSON serialization and progression need native probes.
"""
from policy_harness import ROOT, body, run
admin = ROOT/'addons/core/Scripts/Game/ERR/ERR_AdminService.c'
service = ROOT/'addons/core/Scripts/Game/ERR/ERR_TimeService.c'
settings = ROOT/'addons/core/Scripts/Game/ERR/ERR_Settings.c'
def translate(source):
return (source.replace('string ', 'std::string ').replace('out int ', 'int& ')
.replace('text.Length()', 'int(text.size())').replace('.IsEmpty()', '.empty()')
.replace('.Substring(', '.substr(')
.replace('"0123456789".IndexOf(', 'std::string("0123456789").find(')
.replace(' < 0) return false;', ' == std::string::npos) return false;')
.replace('text.ToInt()', 'std::stoi(text)')
.replace('hours.ToString()', 'std::to_string(hours)')
.replace('remainder.ToString()', 'std::to_string(remainder)')
.replace('ERR_CommandArguments.Integer', 'Integer')
.replace('ERR_Settings.Valid', 'Valid'))
functions = '\n'.join(translate(body(path, signature)) for path, signature in (
(settings, 'static bool Valid('),
(settings, 'static int AddedDefault('),
(admin, 'static bool Integer('),
(service, 'static bool ParseClock('),
(service, 'static string Clock('),
(service, 'static float DayDuration('),
))
run('#include <cassert>\n#include <cmath>\n#include <string>\n' + functions + r'''
int main() {
for (int minute=0; minute<1440; ++minute) {
int parsed=-1;
assert(ParseClock(Clock(minute),parsed));
assert(parsed==minute);
}
assert(Clock(0)=="00:00" && Clock(1439)=="23:59" && Clock(375)=="06:15");
assert(Clock(-1)=="unavailable" && Clock(1440)=="unavailable");
for (std::string input : {"", "0:00", "00:0", "24:00", "12:60", "-1:00", "1a:00", "00:0b", "06:15junk", " 06:15", "06:15 ", "06.15"}) {
int parsed=-1; assert(!ParseClock(input,parsed));
}
assert(AddedDefault("startTimeMinutes")==840);
assert(AddedDefault("timeMultiplier")==1);
assert(AddedDefault("radioDefenceSeconds")==-1);
assert(AddedDefault("unknown")==-1);
for (int multiplier=1; multiplier<=24; ++multiplier)
assert(std::abs(DayDuration(multiplier)*multiplier-86400.0)<0.01);
assert(DayDuration(0)==-1 && DayDuration(25)==-1 && DayDuration(-1)==-1);
}
''')
print('PASS: every minute round-trips, malformed clocks rejected, defaults limited to added keys, progression bounds and day duration aligned')