summary refs log tree commit diff
path: root/tests/federation
diff options
context:
space:
mode:
Diffstat (limited to 'tests/federation')
-rw-r--r--tests/federation/__init__.py0
-rw-r--r--tests/federation/test_federation.py240
-rw-r--r--tests/federation/test_pdu_codec.py146
3 files changed, 386 insertions, 0 deletions
diff --git a/tests/federation/__init__.py b/tests/federation/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/federation/__init__.py
diff --git a/tests/federation/test_federation.py b/tests/federation/test_federation.py
new file mode 100644
index 0000000000..1792f9de56
--- /dev/null
+++ b/tests/federation/test_federation.py
@@ -0,0 +1,240 @@
+# trial imports
+from twisted.internet import defer
+from twisted.trial import unittest
+
+# python imports
+from mock import Mock
+import logging
+
+from ..utils import MockHttpServer
+
+from synapse.server import HomeServer
+from synapse.federation import initialize_http_replication
+from synapse.federation.units import Pdu
+from synapse.storage.pdu import PduTuple, PduEntry
+
+
+logging.getLogger().addHandler(logging.NullHandler())
+
+
+def make_pdu(prev_pdus=[], **kwargs):
+    """Provide some default fields for making a PduTuple."""
+    pdu_fields = {
+        "is_state": False,
+        "unrecognized_keys": [],
+        "outlier": False,
+        "have_processed": True,
+        "state_key": None,
+        "power_level": None,
+        "prev_state_id": None,
+        "prev_state_origin": None,
+    }
+    pdu_fields.update(kwargs)
+
+    return PduTuple(PduEntry(**pdu_fields), prev_pdus)
+
+
+class MockClock(object):
+    now = 1000
+
+    def time(self):
+        return self.now
+
+    def time_msec(self):
+        return self.time() * 1000
+
+
+class FederationTestCase(unittest.TestCase):
+    def setUp(self):
+        self.mock_http_server = MockHttpServer()
+        self.mock_http_client = Mock(spec=[
+            "put_json",
+        ])
+        self.mock_persistence = Mock(spec=[
+            "get_current_state_for_context",
+            "get_pdu",
+            "persist_pdu",
+            "update_min_depth_for_context",
+            "prep_send_transaction",
+            "delivered_txn",
+            "get_received_txn_response",
+            "set_received_txn_response",
+        ])
+        self.mock_persistence.get_received_txn_response.return_value = (
+                defer.succeed(None)
+        )
+        self.clock = MockClock()
+        hs = HomeServer("test",
+                http_server=self.mock_http_server,
+                http_client=self.mock_http_client,
+                db_pool=None,
+                datastore=self.mock_persistence,
+                clock=self.clock,
+        )
+        self.federation = initialize_http_replication(hs)
+        self.distributor = hs.get_distributor()
+
+    @defer.inlineCallbacks
+    def test_get_state(self):
+        self.mock_persistence.get_current_state_for_context.return_value = (
+            defer.succeed([])
+        )
+
+        # Empty context initially
+        (code, response) = yield self.mock_http_server.trigger("GET",
+                "/state/my-context/", None)
+        self.assertEquals(200, code)
+        self.assertFalse(response["pdus"])
+
+        # Now lets give the context some state
+        self.mock_persistence.get_current_state_for_context.return_value = (
+            defer.succeed([
+                make_pdu(
+                    pdu_id="the-pdu-id",
+                    origin="red",
+                    context="my-context",
+                    pdu_type="m.topic",
+                    ts=123456789000,
+                    depth=1,
+                    is_state=True,
+                    content_json='{"topic":"The topic"}',
+                    state_key="",
+                    power_level=1000,
+                    prev_state_id="last-pdu-id",
+                    prev_state_origin="blue",
+                ),
+            ])
+        )
+
+        (code, response) = yield self.mock_http_server.trigger("GET",
+                "/state/my-context/", None)
+        self.assertEquals(200, code)
+        self.assertEquals(1, len(response["pdus"]))
+
+    @defer.inlineCallbacks
+    def test_get_pdu(self):
+        self.mock_persistence.get_pdu.return_value = (
+            defer.succeed(None)
+        )
+
+        (code, response) = yield self.mock_http_server.trigger("GET",
+                "/pdu/red/abc123def456/", None)
+        self.assertEquals(404, code)
+
+        # Now insert such a PDU
+        self.mock_persistence.get_pdu.return_value = (
+            defer.succeed(
+                make_pdu(
+                    pdu_id="abc123def456",
+                    origin="red",
+                    context="my-context",
+                    pdu_type="m.text",
+                    ts=123456789001,
+                    depth=1,
+                    content_json='{"text":"Here is the message"}',
+                )
+            )
+        )
+
+        (code, response) = yield self.mock_http_server.trigger("GET",
+                "/pdu/red/abc123def456/", None)
+        self.assertEquals(200, code)
+        self.assertEquals(1, len(response["pdus"]))
+        self.assertEquals("m.text", response["pdus"][0]["pdu_type"])
+
+    @defer.inlineCallbacks
+    def test_send_pdu(self):
+        self.mock_http_client.put_json.return_value = defer.succeed(
+                (200, "OK")
+        )
+
+        pdu = Pdu(
+                pdu_id="abc123def456",
+                origin="red",
+                destinations=["remote"],
+                context="my-context",
+                ts=123456789002,
+                pdu_type="m.test",
+                content={"testing": "content here"},
+                depth=1,
+        )
+
+        yield self.federation.send_pdu(pdu)
+
+        self.mock_http_client.put_json.assert_called_with(
+                "remote",
+                path="/send/1000000/",
+                data={
+                    "ts": 1000000,
+                    "origin": "test",
+                    "pdus": [
+                        {
+                            "origin": "red",
+                            "pdu_id": "abc123def456",
+                            "prev_pdus": [],
+                            "ts": 123456789002,
+                            "context": "my-context",
+                            "pdu_type": "m.test",
+                            "is_state": False,
+                            "content": {"testing": "content here"},
+                            "depth": 1,
+                        },
+                    ]
+                }
+        )
+
+    @defer.inlineCallbacks
+    def test_send_edu(self):
+        self.mock_http_client.put_json.return_value = defer.succeed(
+                (200, "OK")
+        )
+
+        yield self.federation.send_edu(
+                destination="remote",
+                edu_type="m.test",
+                content={"testing": "content here"},
+        )
+
+        # MockClock ensures we can guess these timestamps
+        self.mock_http_client.put_json.assert_called_with(
+                "remote",
+                path="/send/1000000/",
+                data={
+                    "origin": "test",
+                    "ts": 1000000,
+                    "pdus": [],
+                    "edus": [
+                        {
+                            "origin": "test",
+                            "destination": "remote",
+                            "edu_type": "m.test",
+                            "content": {"testing": "content here"},
+                        }
+                    ],
+                })
+
+    @defer.inlineCallbacks
+    def test_recv_edu(self):
+        recv_observer = Mock()
+        recv_observer.return_value = defer.succeed(())
+
+        self.federation.register_edu_handler("m.test", recv_observer)
+
+        yield self.mock_http_server.trigger("PUT", "/send/1001000/",
+                """{
+                    "origin": "remote",
+                    "ts": 1001000,
+                    "pdus": [],
+                    "edus": [
+                        {
+                            "origin": "remote",
+                            "destination": "test",
+                            "edu_type": "m.test",
+                            "content": {"testing": "reply here"}
+                        }
+                    ]
+                }""")
+
+        recv_observer.assert_called_with(
+                "remote", {"testing": "reply here"}
+        )
diff --git a/tests/federation/test_pdu_codec.py b/tests/federation/test_pdu_codec.py
new file mode 100644
index 0000000000..688182fa5b
--- /dev/null
+++ b/tests/federation/test_pdu_codec.py
@@ -0,0 +1,146 @@
+# -*- coding: utf-8 -*-
+from twisted.trial import unittest
+
+from synapse.federation.pdu_codec import (
+    PduCodec, encode_event_id, decode_event_id
+)
+from synapse.federation.units import Pdu
+#from synapse.api.events.room import MessageEvent
+
+from synapse.server import HomeServer
+
+from mock import Mock
+
+
+class PduCodecTestCase(unittest.TestCase):
+    def setUp(self):
+        self.hs = HomeServer("blargle.net")
+        self.event_factory = self.hs.get_event_factory()
+
+        self.codec = PduCodec(self.hs)
+
+    def test_decode_event_id(self):
+        self.assertEquals(
+            ("foo", "bar.com"),
+            decode_event_id("foo@bar.com", "A")
+        )
+
+        self.assertEquals(
+            ("foo", "bar.com"),
+            decode_event_id("foo", "bar.com")
+        )
+
+    def test_encode_event_id(self):
+        self.assertEquals("A@B", encode_event_id("A", "B"))
+
+    def test_codec_event_id(self):
+        event_id = "aa@bb.com"
+
+        self.assertEquals(
+            event_id,
+            encode_event_id(*decode_event_id(event_id, None))
+        )
+
+        pdu_id = ("aa", "bb.com")
+
+        self.assertEquals(
+            pdu_id,
+            decode_event_id(encode_event_id(*pdu_id), None)
+        )
+
+    def test_event_from_pdu(self):
+        pdu = Pdu(
+            pdu_id="foo",
+            context="rooooom",
+            pdu_type="m.room.message",
+            origin="bar.com",
+            ts=12345,
+            depth=5,
+            prev_pdus=[("alice", "bob.com")],
+            is_state=False,
+            content={"msgtype": u"test"},
+        )
+
+        event = self.codec.event_from_pdu(pdu)
+
+        self.assertEquals("foo@bar.com", event.event_id)
+        self.assertEquals(pdu.context, event.room_id)
+        self.assertEquals(pdu.is_state, event.is_state)
+        self.assertEquals(pdu.depth, event.depth)
+        self.assertEquals(["alice@bob.com"], event.prev_events)
+        self.assertEquals(pdu.content, event.content)
+
+    def test_pdu_from_event(self):
+        event = self.event_factory.create_event(
+            etype="m.room.message",
+            event_id="gargh_id",
+            room_id="rooom",
+            user_id="sender",
+            content={"msgtype": u"test"},
+        )
+
+        pdu = self.codec.pdu_from_event(event)
+
+        self.assertEquals(event.event_id, pdu.pdu_id)
+        self.assertEquals(self.hs.hostname, pdu.origin)
+        self.assertEquals(event.room_id, pdu.context)
+        self.assertEquals(event.content, pdu.content)
+        self.assertEquals(event.type, pdu.pdu_type)
+
+        event = self.event_factory.create_event(
+            etype="m.room.message",
+            event_id="gargh_id@bob.com",
+            room_id="rooom",
+            user_id="sender",
+            content={"msgtype": u"test"},
+        )
+
+        pdu = self.codec.pdu_from_event(event)
+
+        self.assertEquals("gargh_id", pdu.pdu_id)
+        self.assertEquals("bob.com", pdu.origin)
+        self.assertEquals(event.room_id, pdu.context)
+        self.assertEquals(event.content, pdu.content)
+        self.assertEquals(event.type, pdu.pdu_type)
+
+    def test_event_from_state_pdu(self):
+        pdu = Pdu(
+            pdu_id="foo",
+            context="rooooom",
+            pdu_type="m.room.topic",
+            origin="bar.com",
+            ts=12345,
+            depth=5,
+            prev_pdus=[("alice", "bob.com")],
+            is_state=True,
+            content={"topic": u"test"},
+            state_key="",
+        )
+
+        event = self.codec.event_from_pdu(pdu)
+
+        self.assertEquals("foo@bar.com", event.event_id)
+        self.assertEquals(pdu.context, event.room_id)
+        self.assertEquals(pdu.is_state, event.is_state)
+        self.assertEquals(pdu.depth, event.depth)
+        self.assertEquals(["alice@bob.com"], event.prev_events)
+        self.assertEquals(pdu.content, event.content)
+        self.assertEquals(pdu.state_key, event.state_key)
+
+    def test_pdu_from_state_event(self):
+        event = self.event_factory.create_event(
+            etype="m.room.topic",
+            event_id="gargh_id",
+            room_id="rooom",
+            user_id="sender",
+            content={"topic": u"test"},
+        )
+
+        pdu = self.codec.pdu_from_event(event)
+
+        self.assertEquals(event.event_id, pdu.pdu_id)
+        self.assertEquals(self.hs.hostname, pdu.origin)
+        self.assertEquals(event.room_id, pdu.context)
+        self.assertEquals(event.content, pdu.content)
+        self.assertEquals(event.type, pdu.pdu_type)
+        self.assertEquals(event.state_key, pdu.state_key)