Files
EscapistsReintroduced/tests/test_crash_stock_lifecycle.py
T
2026-11-06 23:26:57 +01:00

45 lines
3.2 KiB
Python

"""Execute the real fill loop against inventory races and delayed insertions."""
from policy_harness import ROOT, body, run
fill=body(ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_CrashSites.c','protected void Fill(')
fill=fill.replace('protected void Fill','void Fill').replace('InventoryItemComponent itemComponent','InventoryItemComponent* itemComponent').replace('InventoryItemComponent.Cast','InventoryItemComponent::Cast').replace('FindComponent(InventoryItemComponent)','FindComponent()').replace('ERR_Actors.DeleteSpawned','ERR_Actors::DeleteSpawned').replace('ERR_CrashLoot.Allowed','ERR_CrashLoot::Allowed').replace('LogLevel.WARNING','0').replace('null','nullptr')
for name in ('m_Pending','m_Inventory','m_Item','itemComponent'):fill=fill.replace(name+'.',name+'->')
fill=fill.replace('Crate.GetOrigin()', 'Crate->GetOrigin()')
run(r'''
#include <cassert>
#include <string>
#include <vector>
#include <algorithm>
using ResourceName=std::string;
struct InventoryItemComponent {bool attached=false;bool GetParentSlot(){return attached;}static InventoryItemComponent* Cast(InventoryItemComponent* p){return p;}};
struct Entity {InventoryItemComponent component;bool removed=false;InventoryItemComponent* FindComponent(){return &component;}std::string GetOrigin(){return "";}};
using IEntity=Entity*;
template<class T> struct array:std::vector<T>{void Insert(T v){this->push_back(v);}bool Contains(T v){return std::find(this->begin(),this->end(),v)!=this->end();}int Count(){return this->size();}};
struct Inventory {bool contains=false,accept=true;IEntity item=nullptr;void GetItems(array<IEntity>& a){if(contains)a.Insert(item);}bool TryInsertItem(IEntity){return accept;}};
namespace ERR_Actors {void DeleteSpawned(IEntity e){e->removed=true;}}
namespace ERR_CrashLoot {bool Allowed(ResourceName){return true;}}
void Print(std::string,int){}
struct Site {IEntity Crate;array<IEntity> Stock;};
struct Worker {
Entity crate,item;Site site;Inventory inventory;
Site* m_Pending=&site;Inventory* m_Inventory=&inventory;IEntity m_Item=nullptr;
bool m_ItemIssued=false,m_Accepted=false,finished=false;
int m_ItemIndex=0,m_ItemTicks=0,spawns=0;
array<ResourceName> m_Loot;
Worker(){site.Crate=&crate;m_Loot.Insert("rifle");m_Loot.Insert("ammo");}
void Finish(){finished=true;}
IEntity Spawn(ResourceName,std::string,std::string){spawns++;return &item;}
''' + fill + r'''
};
int main(){
Worker destroyed;destroyed.m_ItemIssued=true;destroyed.Fill();assert(destroyed.spawns==0&&destroyed.m_ItemIndex==1);
Worker taken;taken.m_Item=&taken.item;taken.m_ItemIssued=true;taken.item.component.attached=true;taken.Fill();
assert(taken.m_ItemIndex==1&&taken.site.Stock.size()==1&&!taken.item.removed&&taken.spawns==0);
Worker delayed;delayed.Fill();assert(delayed.spawns==1);delayed.Fill();assert(delayed.m_Accepted);
for(int i=0;i<12;i++)delayed.Fill();
assert(delayed.spawns==1&&delayed.item.removed&&delayed.m_ItemIndex==1);
Worker success;success.Fill();success.inventory.item=success.m_Item;success.inventory.contains=true;success.Fill();
assert(success.spawns==1&&success.m_ItemIndex==1&&success.site.Stock.size()==1);
}
''')
print('PASS: destroyed grants are not respawned, taken items are retained, and delayed/rejected inserts cannot duplicate loot')