]> git.aero2k.de Git - urlbot-v3.git/commitdiff
implement local message broker for testing
authorThorsten <mail@aero2k.de>
Fri, 19 Apr 2024 15:44:02 +0000 (17:44 +0200)
committerThorsten <mail@aero2k.de>
Fri, 19 Apr 2024 15:44:02 +0000 (17:44 +0200)
with some crude hack to replicate amqp matching

tests/test_integration/bot_test_utils.py
tests/test_integration/conftest.py
tests/test_integration/test_plugins.py

index e102f6eb1c0ff7642e20761c1a3ef8bcf8134fc6..64fca83f0002530435a0be99a9707ec05a2b0d18 100644 (file)
@@ -1,12 +1,15 @@
 # -*- coding: utf-8 -*-
+import re
 from dataclasses import dataclass
 from unittest import mock
 
 import pika.channel
 import pika.spec
+import pytest
 from slixmpp import Message, JID
 
 from distbot.bot.bot import Bot
+from distbot.bot.worker import Worker
 
 
 @dataclass
@@ -26,7 +29,7 @@ class AMQPCallback:
         return AMQPCallback(ch=channel, method=method, properties=props, body=body)
 
 
-def inject_callback(msg: str, sender: str, bot_nick: str):
+def get_amqp_callback_params(msg: str, sender: str, bot_nick: str) -> AMQPCallback:
     # Message interface is used like a dict
     # msg_mock = mock.MagicMock(spec=Message)
     msg_mock = {
@@ -35,4 +38,34 @@ def inject_callback(msg: str, sender: str, bot_nick: str):
         "type": "groupchat",
         "body": msg,
     }
-    return AMQPCallback.from_message(msg=msg_mock, bot_nick=bot_nick).__dict__
+    return AMQPCallback.from_message(msg=msg_mock, bot_nick=bot_nick)
+
+class LocalMessageBroker:
+    def __init__(self):
+        self.recipients = []
+
+    def add_recipient(self, recipient: Worker):
+        self.recipients.append(recipient)
+
+    def route_message(self, msg: str, sender: str, bot_nick: str):
+        params = get_amqp_callback_params(msg, sender, bot_nick)
+        for recipient in self.recipients:
+            for binding_key in recipient.binding_keys:
+                if self.matches(binding_key, params.method.routing_key):
+                    recipient.callback(**params.__dict__)
+                    break
+
+    @staticmethod
+    def matches(binding_key, message_routing_key):
+        regex = binding_key.replace('.', '\\.').replace('*', '[^.]+').replace('#', '.*')
+        # fix .# leading to \..*
+        regex = re.sub(r"\\.\.\*$", ".*", regex)
+        return re.fullmatch(regex, message_routing_key) is not None
+
+
+@pytest.mark.parametrize("bind,msg_routing_key", [
+    ("nick.dice.#", "nick.dice"),
+    ("nick.dice.#", "nick.dice.2"),
+])
+def test_local_message_broker(bind, msg_routing_key):
+    assert LocalMessageBroker.matches(bind, msg_routing_key)
\ No newline at end of file
index 015e2ce1cdb05415c0ced54cfd64a1707210fe70..f7626896d90902ec76e573dc132239add9c38274 100644 (file)
@@ -6,6 +6,7 @@ import pytest
 
 from distbot.bot import worker
 from distbot.plugins import openai
+from bot_test_utils import LocalMessageBroker
 
 
 @pytest.fixture(name="send_action")
@@ -37,4 +38,14 @@ def mock_openai(monkeypatch):
 
 @pytest.fixture
 def bot_nick():
-    return "doofibot"
\ No newline at end of file
+    return "doofibot"
+
+@pytest.fixture(scope="function")
+def message_broker():
+    lmb = LocalMessageBroker()
+    # TODO another fixture maybe
+    # from distbot.minijobber.run import PLUGIN_MODULES
+    # for plugin_bunch in PLUGIN_MODULES.values():
+    #     for plugin in plugin_bunch:
+    #         lmb.add_recipient(plugin(None))
+    return lmb
index 1d1955d58bb581b32dd7e04002218b788bf4e9c9..a83f8c3e62713d4561fba6958a0ffdf642d02cd2 100644 (file)
@@ -5,7 +5,6 @@ import pytest
 
 from distbot.common.action import Action
 from distbot.plugins.basic import Dice, Choose
-from tests.test_integration.bot_test_utils import inject_callback
 
 """
 Goal: have a parameterized pipeline of 
@@ -17,15 +16,15 @@ It should
 2. [somehow] replicate matching of rabbitmq topic
 3. invoke Worker-interface with the raw body? using Worker.callback(..)  
 
-TODO: plugins.resolve(message).callback() for (2)
 """
 
 @pytest.mark.parametrize(["dice_count"], argvalues=(
         [None], [1], [3], [100]
 ))
-def test_dice(send_action, randomint, bot_nick, dice_count):
+def test_dice(send_action, randomint, bot_nick, dice_count, message_broker):
     args = f" {dice_count}" if dice_count else ""
-    Dice(None).callback(**inject_callback(msg=f"{bot_nick}: dice" + args, sender="you", bot_nick=bot_nick))
+    message_broker.add_recipient(Dice(None))
+    message_broker.route_message(msg=f"{bot_nick}: dice" + args, sender="you", bot_nick=bot_nick)
 
     result = {
         "None": "rolling a dice for you: ⚂ (​3​)",
@@ -46,10 +45,11 @@ def test_dice(send_action, randomint, bot_nick, dice_count):
         [2, "do_something do_nothing"],
         [3, """ "to do something" "to do nothing" """],
 ))
-def test_quoted_choose(send_action, mock_openai, randomchoice, bot_nick, i, choices, monkeypatch):
+def test_quoted_choose(send_action, mock_openai, randomchoice, bot_nick, i, choices, monkeypatch, message_broker):
     with mock.patch.object(Choose, "weighted_choice") as mock_weighted_choice:
         mock_weighted_choice.side_effect = lambda l: l[0][0]  # first option wins
-        Choose(None).callback(**inject_callback(msg=f"{bot_nick}: choose " + choices, sender="you", bot_nick=bot_nick))
+        message_broker.add_recipient(Choose(None))
+        message_broker.route_message(msg=f"{bot_nick}: choose " + choices, sender="you", bot_nick=bot_nick)
 
     result = {
         0: "you: Yes.",