Files
EscapistsReintroduced/tests/test_inventory_enumeration_policy.py
T

79 lines
3.3 KiB
Python

"""Synthetic identity regression using actual Enforce inventory/count method bodies.
This checks source policy only; it does not simulate native inventory transfers.
"""
import unittest
from policy_harness import ROOT, body, run
def translated(source):
for old, new in [
('InventoryStorageManagerComponent inventory', 'InventoryStorageManagerComponent* inventory'),
('notnull array<IEntity> items', 'Array<Entity*>& items'),
('out array<IEntity> items', 'Array<Entity*>& items'),
('array<IEntity>', 'Array<Entity*>'),
('IEntity item', 'Entity* item'),
('foreach (', 'for ('),
('inventory.GetItems', 'inventory->GetItems'),
('item.GetPrefabData()', 'item->GetPrefabData()'),
('.GetPrefabName()', '->GetPrefabName()'),
('ERR_Inventory.', 'ERR_Inventory::'),
('int count;', 'int count = 0;'),
]:
source = source.replace(old, new)
return source
class InventoryEnumerationPolicy(unittest.TestCase):
def test_duplicate_references_distinct_rounds_and_cross_inventory_union(self):
helper = ROOT / 'addons/core/Scripts/Game/ERR/ERR_Inventory.c'
mortar = ROOT / 'addons/ai/Scripts/Game/ERR/ERR_MortarBattery.c'
methods = '\n'.join(translated(body(helper, signature)) for signature in (
'static int AppendUnique(', 'static int Items('))
count = translated(body(mortar, 'int InventoryShells('))
run(r'''
#include <algorithm>
#include <cassert>
#include <string>
#include <vector>
template <typename T> struct Array : std::vector<T> {
using std::vector<T>::vector;
bool Contains(T v) const { return std::find(this->begin(),this->end(),v)!=this->end(); }
void Insert(T v) { this->push_back(v); }
void Clear() { this->clear(); }
int Count() const { return this->size(); }
};
struct Prefab { std::string name; std::string GetPrefabName() { return name; } };
struct Entity { Prefab* prefab; Prefab* GetPrefabData() { return prefab; } };
struct InventoryStorageManagerComponent {
Array<Entity*> raw;
void GetItems(Array<Entity*>& out) { out = raw; }
};
const std::string SHELL = "mortar-shell";
struct ERR_Inventory {
''' + methods + '\n};\n' + count + r'''
int main() {
Prefab shell{SHELL}, watch{"watch"};
Entity roundA{&shell}, roundB{&shell}, watchA{&watch}, missingPrefab{nullptr};
InventoryStorageManagerComponent one{{&roundA,&roundA,nullptr,&roundB,&watchA,&watchA,&missingPrefab}};
Array<Entity*> unique{&watchA};
assert(ERR_Inventory::Items(&one,unique)==4);
assert(unique[0]==&roundA && unique[1]==&roundB && unique[2]==&watchA && unique[3]==&missingPrefab);
assert(InventoryShells(&one)==2); // Different shells share one prefab, not one identity.
assert(one.raw.size()==7 && one.raw[0]==one.raw[1]); // Enumeration remains untouched.
InventoryStorageManagerComponent two{{&roundB,&roundB,&roundA}};
assert(ERR_Inventory::AppendUnique(&two,unique)==4); // Cross-inventory repeated identities.
assert(ERR_Inventory::AppendUnique(nullptr,unique)==4);
assert(ERR_Inventory::Items(nullptr,unique)==0 && unique.empty());
assert(InventoryShells(nullptr)==0);
InventoryStorageManagerComponent repeated{{&roundA,&roundA,&roundA}};
assert(InventoryShells(&repeated)==1);
InventoryStorageManagerComponent empty{{nullptr,&missingPrefab,&watchA}};
assert(InventoryShells(&empty)==0);
}
''')
if __name__ == '__main__':
unittest.main()