85 lines
4.6 KiB
Python
85 lines
4.6 KiB
Python
"""Source policy and actual fixture completion checks; not an engine test."""
|
|
from pathlib import Path
|
|
import unittest
|
|
from policy_harness import body, run
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
SOURCE = ROOT/'addons/ai/Scripts/Game/ERR/ERR_NativeMortarTransferProbe.c'
|
|
|
|
class NativeMortarTransferChecks(unittest.TestCase):
|
|
def test_original_identity_conservation_policy(self):
|
|
method = body(SOURCE, 'static bool Conservation(')
|
|
run(method + '''
|
|
#include <cassert>
|
|
int main() {
|
|
for(int original=0;original<30;original++) for(int actual=0;actual<30;actual++)
|
|
for(int all=0;all<2;all++) for(int unique=0;unique<2;unique++)
|
|
assert(Conservation(original,actual,all,unique)==(original==27 && actual==27 && all && unique));
|
|
}
|
|
''')
|
|
def test_actual_move_completion_requires_callback_slot_and_deadline(self):
|
|
method=body(SOURCE, 'protected int MoveResult(').replace('protected int','int').replace('InventoryItemComponent item;', 'InventoryItemComponent* item;').replace('InventoryItemComponent item =', 'InventoryItemComponent* item =').replace('InventoryItemComponent.Cast','InventoryItemComponent::Cast').replace('FindComponent(InventoryItemComponent)','FindComponent(0)').replace('null','nullptr')
|
|
for name in ('m_MoveCallback','m_MoveShell','m_MoveDestination','item'):
|
|
method=method.replace(name+'.',name+'->')
|
|
method=method.replace('GetParentSlot().', 'GetParentSlot()->')
|
|
run('''
|
|
#include <cassert>
|
|
struct Entity;
|
|
struct Storage { bool has=false; bool Contains(Entity*) { return has; } };
|
|
struct Slot { Storage* storage=nullptr; Storage* GetStorage() { return storage; } };
|
|
struct InventoryItemComponent {
|
|
Slot* slot=nullptr;
|
|
static InventoryItemComponent* Cast(InventoryItemComponent* x) { return x; }
|
|
Slot* GetParentSlot() { return slot; }
|
|
};
|
|
struct Entity { InventoryItemComponent* item=nullptr; InventoryItemComponent* FindComponent(int) { return item; } };
|
|
struct Callback { int Result=0; };
|
|
struct Probe {
|
|
Callback* m_MoveCallback=nullptr; Entity* m_MoveShell=nullptr;
|
|
Storage* m_MoveDestination=nullptr; float m_MoveDeadline=100;
|
|
''' + method + '''
|
|
};
|
|
int main() {
|
|
Probe p; Callback cb; Entity shell; Storage target,wrong; Slot slot; InventoryItemComponent item;
|
|
p.m_MoveCallback=&cb; p.m_MoveShell=&shell; p.m_MoveDestination=⌖
|
|
assert(p.MoveResult(99)==0); // acceptance alone is not completion
|
|
cb.Result=1; assert(p.MoveResult(99)==0); // callback alone is insufficient
|
|
target.has=true; assert(p.MoveResult(99)==0); // exact item metadata required
|
|
shell.item=&item; item.slot=&slot; slot.storage=&wrong;
|
|
assert(p.MoveResult(99)==0); // apparent membership in wrong storage is insufficient
|
|
slot.storage=⌖ assert(p.MoveResult(100)==-1); // bounded deadline
|
|
assert(p.m_MoveCallback==&cb); // failure retains pending operation and borrowed shell
|
|
cb.Result=-1; assert(p.MoveResult(99)==-1);
|
|
cb.Result=1; assert(p.MoveResult(99)==1);
|
|
assert(!p.m_MoveCallback && !p.m_MoveShell && !p.m_MoveDestination);
|
|
assert(p.MoveResult(99)==1); // completion cannot replay an inventory operation
|
|
}
|
|
''')
|
|
def test_no_shell_creation_or_mutation_and_safe_cleanup(self):
|
|
source=SOURCE.read_text()
|
|
self.assertEqual(source.count('ERR_Actors.Spawn('),1)
|
|
self.assertIn('ERR_Actors.Spawn(STORE,',source)
|
|
for forbidden in ('TrySpawnPrefab', 'SetHealth(', 'ForceUnconsciousness', 'DeleteRplEntity', 'TotalShots++', 'LoadMagazine', 'GetShootingLogic'):
|
|
self.assertNotIn(forbidden,source)
|
|
self.assertNotRegex(source,r'TotalShots\s*=(?!=)')
|
|
stop=body(SOURCE,'void Stop()')
|
|
self.assertIn('if (!m_MoveCallback)',stop)
|
|
self.assertIn('storage && items.IsEmpty()',stop)
|
|
self.assertIn('m_System.Stop()',stop)
|
|
self.assertEqual(source.count('ERR_Actors.DeleteSpawned('),1)
|
|
def test_scoped_hook_cancel_and_exact_request_capture(self):
|
|
source=SOURCE.read_text()
|
|
self.assertTrue(source.startswith('#ifdef WORKBENCH'))
|
|
self.assertIn('outcome == "mortar-transfer"',source)
|
|
self.assertIn('if (m_ERRTransferFixture) return;',source)
|
|
self.assertIn('super.Tick(now);',source)
|
|
self.assertIn('m_CallbackAtCancel = m_ObservedTransfer.ERR_CallbackState()',source)
|
|
self.assertIn('m_ObservedTransfer.CapturedOrder() == m_Battery.OrderId',source)
|
|
self.assertIn('m_Battery.OrderId != m_CancelOrder',source)
|
|
self.assertIn('m_Battery.ERR_TransferAttempts() != m_AttemptsAtStart + 2',source)
|
|
self.assertIn('late callback timing not exercised',source)
|
|
self.assertIn('Has(entry.OriginalOwner, entry.Shell)',source)
|
|
self.assertEqual(body(SOURCE,'protected bool BeginMove(').count('TryMoveItemToStorage('),1)
|
|
self.assertIn('return BeginMove(shell, storage, now)',body(SOURCE,'protected bool Stash('))
|
|
|
|
if __name__=='__main__': unittest.main()
|