Files
EscapistsReintroduced/tests/test_local_admission.py
T

90 lines
6.5 KiB
Python

"""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')