Files
EscapistsReintroduced/tests/test_admin_tick_delivery.py
T

52 lines
3.9 KiB
Python

"""Actual session Tick and journal router keep tool completions/feed deliveries separate."""
from policy_harness import ROOT, body, run
session=ROOT/'addons/core/Scripts/Game/ERR/ERR_AdminSession.c'
admin=ROOT/'addons/core/Scripts/Game/ERR/ERR_AdminService.c'
tick=body(session,'bool Tick(')
reader=body(admin,'bool ReadJournal(')
def adapt(s):
s=s.replace('array<string> replies = {};','Array<string> replies;')
s=s.replace('array<string> lines','Array<string>& lines').replace('out int cursor','int& cursor')
s=s.replace('foreach (string reply : replies)', 'for (string reply : replies)').replace('foreach (string line : replies)', 'for (string line : replies)')
s=s.replace('foreach (ERR_AdminProvider provider : m_Providers)', 'for (Provider* provider : m_Providers)')
for name in ['m_Tools','m_Controller','m_Mode','provider']:
s=s.replace(name+'.',name+'->')
s=s.replace('GetGame().','GetGame()->').replace('GetWorld().','GetWorld()->').replace('Admin().','Admin()->')
return s
run(r'''
#include <cassert>
#include <string>
#include <vector>
using string=std::string;
template<class T>struct Array:std::vector<T>{void Clear(){this->clear();}void Insert(T value){this->push_back(value);}};
struct Provider{Array<string> journal;int calls=0;bool ReadJournal(int after,Array<string>& lines,int& cursor,int limit){calls++;cursor=after;for(int i=after;i<int(journal.size())&&limit>0;i++,limit--){lines.Insert(journal[i]);cursor=i+1;}return true;}};
struct Admin{Array<Provider*> m_Providers;
'''+adapt(reader)+r'''
};
struct Mode{struct Admin admin;struct Admin* Admin(){return &admin;}};
struct Tools{Array<string> pending;int ticks=0;void Tick(Array<string>& replies){ticks++;for(auto line:pending)replies.Insert(line);pending.clear();}};
struct Controller{Array<string> received;void ERR_AdminDeliverReply(int token,string reply,bool menu){assert(token==7&&!menu);received.Insert(reply);}};
struct Game{float now=0;Game* GetWorld(){return this;}float GetWorldTime(){return now;}}game;Game* GetGame(){return &game;}
struct Session{
bool allowed=true,m_Live=true;int m_Token=7,m_Cursor=0,bodyChecks=0;float m_NextFeed=0;Mode* m_Mode;Tools* m_Tools;Controller* m_Controller;
bool Authorize(){return allowed;}void CheckBody(){bodyChecks++;}
'''+adapt(tick)+r'''
};
int main(){
Mode mode;Tools tools;Controller controller;Provider provider;mode.admin.m_Providers.Insert(&provider);
provider.journal.Insert("hq1");provider.journal.Insert("hq2");tools.pending.Insert("grant complete");
Session session{true,true,7,0,0,0,&mode,&tools,&controller};
assert(session.Tick());assert(controller.received.size()==3);
assert(controller.received[0]=="grant complete"&&controller.received[1]=="hq1"&&controller.received[2]=="hq2");
assert(session.m_Cursor==2&&session.m_NextFeed==2000);
game.now=1000;assert(session.Tick());assert(controller.received.size()==3&&provider.calls==1);
game.now=2000;tools.pending.Insert("grant failed");assert(session.Tick());assert(controller.received.size()==4&&controller.received[3]=="grant failed");
game.now=4000;provider.journal.Insert("hq3");assert(session.Tick());assert(controller.received.size()==5&&controller.received[4]=="hq3");
session.m_Live=false;game.now=6000;tools.pending.Insert("grant timeout");assert(session.Tick());assert(controller.received.size()==6&&provider.calls==3);
session.m_Live=true;session.allowed=false;game.now=8000;tools.pending.Insert("must not deliver");assert(!session.Tick());assert(controller.received.size()==6&&provider.calls==3&&tools.pending.size()==1);
// No provider still clears tool replies before the live-feed loop.
session.allowed=true;mode.admin.m_Providers.clear();assert(session.Tick());assert(controller.received.size()==7&&controller.received.back()=="must not deliver");
}
''')
print('PASS: actual session Tick + journal router delivers each grant completion and new HQ line once, without repeats on empty/unavailable feeds or unauthorized ticks')