From 94be46979e6aedc4f7104c30e6823373e5533886 Mon Sep 17 00:00:00 2001 From: Nomads_Reach <144523850+NomadsReach@users.noreply.github.com> Date: Sat, 15 Aug 2026 21:54:39 -0400 Subject: [PATCH] Test scoped NPC authority epochs --- server/tests/test_npc_authority.py | 60 ++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 server/tests/test_npc_authority.py diff --git a/server/tests/test_npc_authority.py b/server/tests/test_npc_authority.py new file mode 100644 index 0000000..72ba029 --- /dev/null +++ b/server/tests/test_npc_authority.py @@ -0,0 +1,60 @@ +from __future__ import annotations + +from npc_authority import NpcAuthorityManager, ScopeKey, scope_from_transform + + +def test_first_player_in_scope_becomes_authority() -> None: + manager = NpcAuthorityManager() + scope = ScopeKey("00000010", "0000003C") + changes = manager.reconcile([(7, scope), (4, scope)]) + assert len(changes) == 1 + assignment = manager.get(scope) + assert assignment is not None + assert assignment.player_id == 4 + assert assignment.epoch == 1 + assert manager.authorize(4, scope, 1) + assert not manager.authorize(7, scope, 1) + + +def test_disconnect_reassigns_and_increments_epoch() -> None: + manager = NpcAuthorityManager() + scope = ScopeKey("00000010", "0000003C") + manager.reconcile([(1, scope), (2, scope)]) + changes = manager.reconcile([(2, scope)]) + assert len(changes) == 1 + assert changes[0].previous_player_id == 1 + assert changes[0].player_id == 2 + assert changes[0].epoch == 2 + assert not manager.authorize(1, scope, 1) + assert manager.authorize(2, scope, 2) + + +def test_two_scopes_have_independent_authorities() -> None: + manager = NpcAuthorityManager() + a = ScopeKey("00000010", "0000003C") + b = ScopeKey("00000020", "0000003C") + manager.reconcile([(5, a), (2, a), (7, b), (9, b)]) + assert manager.get(a).player_id == 2 + assert manager.get(b).player_id == 7 + assert manager.get(a).epoch == 1 + assert manager.get(b).epoch == 1 + + +def test_empty_scope_revokes_and_future_reentry_uses_new_epoch() -> None: + manager = NpcAuthorityManager() + scope = ScopeKey("00000010", "") + manager.reconcile([(1, scope)]) + revoked = manager.reconcile([]) + assert revoked[0].player_id == 0 + assert revoked[0].epoch == 2 + assert manager.get(scope) is None + granted = manager.reconcile([(3, scope)]) + assert granted[0].player_id == 3 + assert granted[0].epoch == 3 + + +def test_scope_from_transform_normalizes_form_ids() -> None: + scope = scope_from_transform({"cellId": "1a", "worldspaceId": "3c"}) + assert scope == ScopeKey("0000001A", "0000003C") + assert scope_from_transform(None) is None + assert scope_from_transform({"cellId": ""}) is None