Files
EscapistsReintroduced/tests/test_server_log_regressions.py
T
jakub 6a667d8deb Capture current mission, AI, map and administration development
Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
2026-10-13 22:52:53 +02:00

58 lines
4.6 KiB
Python

"""Execute production guards for the 29 September server exceptions."""
from policy_harness import ROOT, body, run
core=ROOT/'addons/core/Scripts/Game/ERR/00_Core'
ai=ROOT/'addons/core/Scripts/Game/ERR/10_AI'
mark=body(ai/'ERR_EnemyMapMarking.c','override void MarkTarget(')
mark=mark.replace('override ','').replace('notnull SCR_AITargetInfo targetInfo','Target* targetInfo').replace('notnull SCR_AIGroup spottingGroup','Group* spottingGroup').replace('targetInfo.','targetInfo->').replace('spottingGroup.','spottingGroup->').replace('super.MarkTarget','NativeMark')
run('''#include <cassert>
struct Target{void* m_Faction=nullptr;void* m_Entity=nullptr;};
struct Group{void* leader=nullptr;void* GetLeaderEntity(){return leader;}};
struct Marking{int marks=0;void NativeMark(Target*,Group*){marks++;}
'''+mark+'''};
int main(){Marking m;Target t;Group g;g.leader=&g;t.m_Entity=&t;
for(int i=0;i<1100;i++){m.MarkTarget(&t,&g);}assert(!m.marks&&!t.m_Faction&&t.m_Entity==&t);
t.m_Faction=&t;t.m_Entity=nullptr;m.MarkTarget(&t,&g);assert(!m.marks);
t.m_Entity=&t;g.leader=nullptr;m.MarkTarget(&t,&g);assert(!m.marks);
g.leader=&g;m.MarkTarget(&t,&g);assert(m.marks==1);}
''')
methods='\n'.join(body(core/'ERR_GameMode.c',f'Faction {side}Faction(') for side in ['Player','Enemy'])
methods=methods.replace('FactionManager manager','Manager* manager').replace('Faction ','Faction* ').replace('GetGame().','GetGame()->').replace('manager.','manager->').replace('m_Factions.','m_Factions->').replace('return null','return nullptr')
run('''#include <cassert>
#include <string>
struct Key:std::string{using std::string::operator=;bool IsEmpty(){return empty();}};
struct Faction{} player,enemy;
struct Manager{Faction* GetFactionByKey(Key k){return k=="player"?&player:&enemy;}};
struct Game{Manager* manager=nullptr;Manager* GetFactionManager(){return manager;}};
Game* game=nullptr;Game* GetGame(){return game;}
struct Catalog{int queries=0;Faction* PlayerFaction(){queries++;return &player;}Faction* EnemyFaction(){queries++;return &enemy;}};
struct Mode{Catalog* m_Factions=nullptr;Key m_SelectedPlayerFaction,m_SelectedEnemyFaction;
'''+methods+'''};
int main(){Mode m;Catalog c;Game g;Manager mgr;
assert(!m.PlayerFaction()&&!m.EnemyFaction());m.m_Factions=&c;
assert(!m.PlayerFaction()&&!m.EnemyFaction());game=&g;
assert(!m.PlayerFaction()&&!m.EnemyFaction()&&!c.queries);g.manager=&mgr;
assert(m.PlayerFaction()==&player&&m.EnemyFaction()==&enemy&&c.queries==2);
m.m_SelectedPlayerFaction="player";m.m_SelectedEnemyFaction="enemy";
assert(m.PlayerFaction()==&player&&m.EnemyFaction()==&enemy&&c.queries==2);
g.manager=nullptr;assert(!m.PlayerFaction()&&!m.EnemyFaction()&&c.queries==2);}
''')
# Execute actual deletion callback; capture queries/engine writes must never run
# in either active-entity deletion or late world teardown.
delete=body(ai/'ERR_ReconFlightComponent.c','override void OnDelete(')
delete=delete.replace('override ','').replace('IEntity owner','int owner').replace('Replication.','Replication::').replace('ERR_HQ hq = ERR_HQ.Get();','HQ* hq = HQ::Get();').replace('m_Mode.','m_Mode->').replace('hq.','hq->').replace('Recon().','Recon()->').replace('super.OnDelete','NativeDelete')
release=body(ai/'ERR_ReconFlightComponent.c','void Release(').replace('ERR_ReconPhase.','Phase::').replace('EntityEvent.SIMULATE','1')
run('''#include <cassert>
namespace Phase{enum{CREW,RELEASED};}
struct Replication{static bool IsServer(){return true;}};
struct Mode{bool Active(){return true;}};
struct HQ{int removed=0;static HQ* instance;static HQ* Get(){return instance;}HQ* Recon(){return this;}void Removed(void*){removed++;}};
HQ* HQ::instance=nullptr;
struct Flight{int m_Phase=Phase::CREW,queries=0,engines=0,cleared=0,deleted=0;bool m_Aircraft=true,locked=true;Mode* m_Mode=nullptr;
int GetOwner(){return 1;}void ClearEventMask(int,int){cleared++;}bool Captured(){queries++;return false;}void Engines(bool){engines++;}void Locks(bool v){locked=v;}void NativeDelete(int){deleted++;}
'''+release+'\n'+delete+'''};
int main(){Flight teardown;teardown.OnDelete(1);assert(!teardown.queries&&!teardown.engines&&!teardown.locked&&teardown.cleared==1&&teardown.deleted==1);
HQ hq;HQ::instance=&hq;Mode mode;Flight active;active.m_Mode=&mode;active.OnDelete(1);assert(hq.removed==1&&!active.queries&&!active.engines&&!active.locked);
Flight normal;normal.Release(false);assert(normal.queries==1&&normal.engines==1&&!normal.locked);normal.Release(false);assert(normal.engines==1&&normal.cleared==1);}
''')
print('PASS: factionless/deleted map targets do not abort perception; faction lookup tolerates teardown; deleting helicopter releases without capture/engine access')