mirror of
https://github.com/pyMC-dev/pyMC_Repeater.git
synced 2026-08-12 03:43:04 +02:00
refactor(repeater): consolidate identity collision validation
The startup preflight re-implemented the identity collision rules in main.py, reconstructing IdentityManager state by string-parsing its 'type:name' labels, and every configured identity was parsed and constructed twice (once for preflight, once for loading), duplicating config warnings on each start. Move batch validation into IdentityManager.validate_specs(), which checks a batch of IdentitySpec entries against registered identities and against each other without mutating state, and relocate IdentityConfigurationError next to it. The daemon now parses room server and companion configs once during preflight and the identity loaders reuse the cached specs.
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
from repeater.identity_manager import IdentityManager
|
||||
import pytest
|
||||
|
||||
from repeater.identity_manager import IdentityConfigurationError, IdentityManager, IdentitySpec
|
||||
|
||||
|
||||
class _FakeIdentity:
|
||||
@@ -67,3 +69,60 @@ def test_identity_manager_list_handles_none_identity_fields():
|
||||
listed = mgr.list_identities()
|
||||
assert listed[0]["address"] == "N/A"
|
||||
assert listed[0]["public_key"] is None
|
||||
|
||||
|
||||
def test_validate_specs_rejects_intra_batch_hash_collision():
|
||||
mgr = IdentityManager(config={})
|
||||
id_a = _FakeIdentity(bytes([0x11]) + b"A" * 31)
|
||||
id_b = _FakeIdentity(bytes([0x11]) + b"B" * 31)
|
||||
|
||||
with pytest.raises(IdentityConfigurationError, match="one-byte public-key prefixes"):
|
||||
mgr.validate_specs(
|
||||
[
|
||||
IdentitySpec("alpha", id_a, {}, "repeater"),
|
||||
IdentitySpec("beta", id_b, {}, "companion"),
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def test_validate_specs_rejects_intra_batch_duplicate_name():
|
||||
mgr = IdentityManager(config={})
|
||||
id_a = _FakeIdentity(bytes([0x11]) + b"A" * 31)
|
||||
id_b = _FakeIdentity(bytes([0x22]) + b"B" * 31)
|
||||
|
||||
with pytest.raises(IdentityConfigurationError, match="repeater:alpha"):
|
||||
mgr.validate_specs(
|
||||
[
|
||||
IdentitySpec("alpha", id_a, {}, "repeater"),
|
||||
IdentitySpec("alpha", id_b, {}, "companion"),
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def test_validate_specs_rejects_registered_collisions_without_mutation():
|
||||
mgr = IdentityManager(config={})
|
||||
id_a = _FakeIdentity(bytes([0x11]) + b"A" * 31)
|
||||
id_hash_collision = _FakeIdentity(bytes([0x11]) + b"B" * 31)
|
||||
id_name_collision = _FakeIdentity(bytes([0x22]) + b"C" * 31)
|
||||
|
||||
assert mgr.register_identity("alpha", id_a, {}, "repeater") is True
|
||||
|
||||
with pytest.raises(IdentityConfigurationError, match="conflicts"):
|
||||
mgr.validate_specs([IdentitySpec("beta", id_hash_collision, {}, "companion")])
|
||||
with pytest.raises(IdentityConfigurationError, match="already registered"):
|
||||
mgr.validate_specs([IdentitySpec("alpha", id_name_collision, {}, "companion")])
|
||||
|
||||
# Validation never registers anything.
|
||||
assert mgr.get_identity_by_hash(0x22) is None
|
||||
assert mgr.get_identity_by_name("beta") is None
|
||||
|
||||
|
||||
def test_validate_specs_accepts_distinct_batch():
|
||||
mgr = IdentityManager(config={})
|
||||
mgr.validate_specs(
|
||||
[
|
||||
IdentitySpec("alpha", _FakeIdentity(bytes([0x11]) + b"A" * 31), {}, "repeater"),
|
||||
IdentitySpec("beta", _FakeIdentity(bytes([0x22]) + b"B" * 31), {}, "room_server"),
|
||||
IdentitySpec("gamma", _FakeIdentity(bytes([0x33]) + b"C" * 31), {}, "companion"),
|
||||
]
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user