"""Run production bounded journal methods against clock/file/callqueue doubles.""" from policy_harness import ROOT, body, run p = ROOT / 'addons/core/Scripts/Game/ERR/10_AI/ERR_EquipmentLog.c' s = '\n'.join(body(p, signature) for signature in ( 'static string Clean(', 'protected void Enqueue(', 'protected void Schedule(', 'protected string Path(', 'protected void Pump(')) s = s.replace('protected ', '').replace('string.Format', 'Format') s = s.replace('string.Empty', 'string()').replace('FileHandle file', 'File* file') s = s.replace('FileMode.', 'FileMode::').replace('LogLevel.WARNING', '0').replace('level: ', '') s = s.replace('GetGame().GetWorld().GetWorldTime()', 'worldTime') s = s.replace('GetGame().GetCallqueue().CallLater(Pump, delay, false)', 'delays.push_back(delay)') s = s.replace('System.GetTickCount()', 'ticks').replace('Replication.IsServer()', 'server') s = s.replace('FileIO.OpenFile', 'OpenFile').replace('file.', 'file->') run(r''' #include #include #include #include #include struct string:std::string { using std::string::string; string(std::string value):std::string(value){} int Length(){return size();} string Substring(int start,int count){return substr(start,count);} void Replace(string before,string after){size_t i=0;while((i=find(before,i))!=npos){replace(i,before.size(),after);i+=after.size();}} }; templatestd::string show(T value){std::ostringstream s;s<string Format(string pattern,T...args){ std::vector values{show(args)...}; for(size_t i=0;istruct Array:std::vector{void Resize(int n){this->resize(n);}}; int ticks=0,worldTime=17,writeCost=0,opens=0,warnings=0; bool server=true,openOk=true; std::vector delays; enum class FileMode {APPEND,WRITE}; struct File{ std::vector rows;int length=0,closes=0; void WriteLine(string line){rows.push_back(line);length+=line.size()+1;ticks+=writeCost;} int GetLength(){return length;}void Close(){closes++;} } disk; string lastPath;FileMode lastMode; File* OpenFile(string path,FileMode mode){opens++;lastPath=path;lastMode=mode;if(!openOk)return nullptr;if(mode==FileMode::WRITE)disk.length=0;return &disk;} void PrintFormat(string,string,int){warnings++;} struct Journal { Array m_Pending; int m_Head=0,m_Count=0,m_Lost=0,m_Sequence=0,m_Part=0; bool m_Truncate=false,m_Scheduled=false,m_Warned=false; string m_Run="test"; Journal(){m_Pending.Resize(4096);} ''' + s + r''' }; int main(){ // One wakeup for a burst; constant ring storage, no disk IO at enqueue time. Journal journal; for(int i=0;i<4097;i++)journal.Enqueue("ROW",std::to_string(i)); assert(journal.m_Count==4096&&journal.m_Lost==1&&journal.m_Pending.size()==4096); assert(opens==0&&delays.size()==1&&delays.back()==500); // File failure preserves rows; bounded retry and only one warning. openOk=false;journal.Pump();journal.Pump(); assert(journal.m_Count==4096&&journal.m_Lost==1&&warnings==1&&delays.back()==30000); openOk=true;journal.Pump(); assert(journal.m_Count==4064&&journal.m_Lost==0&&disk.rows.size()==33); assert(disk.rows[0].find("LOG_GAP dropped=1")!=string::npos); assert(disk.rows[1].find("seq=1 ")!=string::npos); // Freed slots can immediately be reused without shifting the remaining ring. journal.Enqueue("ROW","new");assert(journal.m_Count==4065); while(journal.m_Count>0)journal.Pump(); assert(disk.rows.size()==4098&&disk.rows.back().find("seq=4098 ")!=string::npos); int idleOpens=opens;journal.Pump();assert(opens==idleOpens&&!journal.m_Scheduled); // Slow native IO ends the slice after one record, without losing following rows. writeCost=4;Journal slow;slow.Enqueue("ROW","a");slow.Enqueue("ROW","b"); slow.Pump();assert(slow.m_Count==1&&slow.m_Scheduled);slow.Pump();assert(slow.m_Count==0); writeCost=0; // Four bounded file slots; truncate only when opening the next rotated slot. Journal rotating; for(int part=0;part<5;part++){ disk.length=2097152;rotating.Enqueue("ROW","rotate");rotating.m_Truncate=false;rotating.Pump(); assert(rotating.m_Part==(part+1)%4&&rotating.m_Truncate); } rotating.Enqueue("ROW","next");rotating.Pump();assert(lastMode==FileMode::WRITE&&!rotating.m_Truncate); assert(lastPath=="$logs:rereintroduced-equipment-1.log"); assert(Journal::Clean("a\nb\rc\td")=="a b c d"); assert(Journal::Clean(string(2000,'x')).Length()==1035); // A client cannot write even if an old callback fires. server=false;Journal client;client.Enqueue("ROW","ignored");idleOpens=opens;client.Pump();assert(opens==idleOpens); } ''') print('PASS: production equipment journal ring bounds, gap notices, retries, flush budget, rotation, idle/server guards and sanitization')