test: add unit tests for plugin registry and event bus
This commit is contained in:
parent
f34c805b84
commit
a1659531c7
139
tests/unit/test_plugin_registry.py
Normal file
139
tests/unit/test_plugin_registry.py
Normal file
@ -0,0 +1,139 @@
|
||||
import pytest
|
||||
|
||||
from proxy_pool.plugins.protocols import CheckContext, CheckResult, DiscoveredProxy, Event
|
||||
from proxy_pool.plugins.registry import PluginConflictError, PluginNotFoundError, PluginRegistry, PluginValidationError
|
||||
|
||||
|
||||
class FakeParser:
|
||||
name = "fake"
|
||||
|
||||
def supports(self, url: str) -> bool:
|
||||
return "fake" in url
|
||||
|
||||
async def parse(self, raw, source_url, source_id, default_protocol):
|
||||
return [DiscoveredProxy(ip="1.2.3.4", port=8080, protocol="http")]
|
||||
|
||||
def default_schedule(self):
|
||||
return None
|
||||
|
||||
|
||||
class FakeChecker:
|
||||
name = "fake_check"
|
||||
stage = 1
|
||||
priority = 0
|
||||
timeout = 5.0
|
||||
|
||||
async def check(self, proxy_ip, proxy_port, proxy_protocol, context):
|
||||
return CheckResult(passed=True, detail="ok")
|
||||
|
||||
def should_skip(self, proxy_protocol):
|
||||
return False
|
||||
|
||||
|
||||
class FakeNotifier:
|
||||
name = "fake_notify"
|
||||
subscribes_to = ["test.*"]
|
||||
notified_events: list[Event]
|
||||
|
||||
def __init__(self):
|
||||
self.notified_events = []
|
||||
|
||||
async def notify(self, event):
|
||||
self.notified_events.append(event)
|
||||
|
||||
async def health_check(self):
|
||||
return True
|
||||
|
||||
|
||||
class TestParserRegistration:
|
||||
def test_register_and_retrieve(self):
|
||||
registry = PluginRegistry()
|
||||
parser = FakeParser()
|
||||
registry.register_parser(parser)
|
||||
|
||||
assert registry.get_parser("fake") is parser
|
||||
|
||||
def test_duplicate_name_raises_conflict(self):
|
||||
registry = PluginRegistry()
|
||||
registry.register_parser(FakeParser())
|
||||
|
||||
with pytest.raises(PluginConflictError):
|
||||
registry.register_parser(FakeParser())
|
||||
|
||||
def test_get_missing_parser_raises(self):
|
||||
registry = PluginRegistry()
|
||||
|
||||
with pytest.raises(PluginNotFoundError):
|
||||
registry.get_parser("nonexistent")
|
||||
|
||||
def test_get_parser_for_url(self):
|
||||
registry = PluginRegistry()
|
||||
parser = FakeParser()
|
||||
registry.register_parser(parser)
|
||||
|
||||
assert registry.get_parser_for_url("http://fake.com/list") is parser
|
||||
assert registry.get_parser_for_url("http://other.com/list") is None
|
||||
|
||||
def test_invalid_plugin_raises_validation_error(self):
|
||||
registry = PluginRegistry()
|
||||
|
||||
with pytest.raises(PluginValidationError):
|
||||
registry.register_parser("not a plugin")
|
||||
|
||||
|
||||
class TestCheckerRegistration:
|
||||
def test_checkers_sorted_by_stage_and_priority(self):
|
||||
registry = PluginRegistry()
|
||||
|
||||
class Late(FakeChecker):
|
||||
name = "late"
|
||||
stage = 2
|
||||
priority = 0
|
||||
|
||||
class Early(FakeChecker):
|
||||
name = "early"
|
||||
stage = 1
|
||||
priority = 0
|
||||
|
||||
class EarlyLow(FakeChecker):
|
||||
name = "early_low"
|
||||
stage = 1
|
||||
priority = 10
|
||||
|
||||
registry.register_checker(Late())
|
||||
registry.register_checker(EarlyLow())
|
||||
registry.register_checker(Early())
|
||||
|
||||
pipeline = registry.get_checker_pipeline()
|
||||
names = [c.name for c in pipeline]
|
||||
assert names == ["early", "early_low", "late"]
|
||||
|
||||
|
||||
class TestEventBus:
|
||||
async def test_emit_notifies_matching_subscribers(self):
|
||||
registry = PluginRegistry()
|
||||
notifier = FakeNotifier()
|
||||
registry.register_notifier(notifier)
|
||||
|
||||
event = Event(type="test.something", payload={"key": "value"})
|
||||
await registry.emit(event)
|
||||
|
||||
# Give the fire-and-forget task a moment to run
|
||||
import asyncio
|
||||
await asyncio.sleep(0.05)
|
||||
|
||||
assert len(notifier.notified_events) == 1
|
||||
assert notifier.notified_events[0].type == "test.something"
|
||||
|
||||
async def test_emit_skips_non_matching(self):
|
||||
registry = PluginRegistry()
|
||||
notifier = FakeNotifier()
|
||||
notifier.subscribes_to = ["other.*"]
|
||||
registry.register_notifier(notifier)
|
||||
|
||||
await registry.emit(Event(type="test.something", payload={}))
|
||||
|
||||
import asyncio
|
||||
await asyncio.sleep(0.05)
|
||||
|
||||
assert len(notifier.notified_events) == 0
|
||||
Loading…
x
Reference in New Issue
Block a user