from __future__ import annotations import pytest from yuxi.channel.security.bot_loop import BotLoopDetector @pytest.mark.unit class TestBotLoopDetector: def test_defaults_allow_within_limit(self) -> None: detector = BotLoopDetector() for _ in range(3): assert detector.is_allowed("user_1", is_bot=True) is True def test_blocks_when_bot_replies_exceed_limit(self) -> None: detector = BotLoopDetector(window_size=5, max_bot_replies=2) assert detector.is_allowed("user_1", is_bot=True) is True assert detector.is_allowed("user_1", is_bot=True) is True assert detector.is_allowed("user_1", is_bot=True) is False def test_non_bot_messages_do_not_increase_bot_count(self) -> None: detector = BotLoopDetector(window_size=5, max_bot_replies=2) assert detector.is_allowed("user_1", is_bot=True) is True assert detector.is_allowed("user_1", is_bot=False) is True assert detector.is_allowed("user_1", is_bot=True) is True assert detector.is_allowed("user_1", is_bot=True) is False def test_window_slides_with_maxlen(self) -> None: detector = BotLoopDetector(window_size=3, max_bot_replies=2) assert detector.is_allowed("user_1", is_bot=True) is True assert detector.is_allowed("user_1", is_bot=True) is True # 3rd bot still allowed because limit is 2 and count is 2 assert detector.is_allowed("user_1", is_bot=True) is False # Adding non-bot drops oldest bot, count becomes 2 -> allowed assert detector.is_allowed("user_1", is_bot=False) is True def test_per_sender_isolation(self) -> None: detector = BotLoopDetector(window_size=3, max_bot_replies=1) assert detector.is_allowed("user_1", is_bot=True) is True assert detector.is_allowed("user_2", is_bot=True) is True assert detector.is_allowed("user_1", is_bot=True) is False assert detector.is_allowed("user_2", is_bot=True) is False def test_all_non_bot_allowed(self) -> None: detector = BotLoopDetector(window_size=3, max_bot_replies=0) for _ in range(5): assert detector.is_allowed("user_1", is_bot=False) is True def test_zero_max_bot_replies_blocks_any_bot(self) -> None: detector = BotLoopDetector(window_size=3, max_bot_replies=0) assert detector.is_allowed("user_1", is_bot=True) is False