Skip to content
Snippets Groups Projects
test_federation.py 9.11 KiB
Newer Older
  • Learn to ignore specific revisions
  • #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #     http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    
    
    matrix.org's avatar
    matrix.org committed
    # trial imports
    from twisted.internet import defer
    
    matrix.org's avatar
    matrix.org committed
    
    # python imports
    
    from mock import Mock, ANY
    
    from ..utils import MockHttpResource, MockClock, setup_test_homeserver
    
    matrix.org's avatar
    matrix.org committed
    
    from synapse.federation import initialize_http_replication
    
    Erik Johnston's avatar
    Erik Johnston committed
    from synapse.events import FrozenEvent
    
    matrix.org's avatar
    matrix.org committed
    def make_pdu(prev_pdus=[], **kwargs):
        """Provide some default fields for making a PduTuple."""
        pdu_fields = {
            "state_key": None,
    
    Erik Johnston's avatar
    Erik Johnston committed
            "prev_events": prev_pdus,
    
    matrix.org's avatar
    matrix.org committed
        }
        pdu_fields.update(kwargs)
    
    
    Erik Johnston's avatar
    Erik Johnston committed
        return FrozenEvent(pdu_fields)
    
    matrix.org's avatar
    matrix.org committed
    
    
    class FederationTestCase(unittest.TestCase):
    
    matrix.org's avatar
    matrix.org committed
        def setUp(self):
    
    matrix.org's avatar
    matrix.org committed
            self.mock_http_client = Mock(spec=[
    
    matrix.org's avatar
    matrix.org committed
                "put_json",
            ])
            self.mock_persistence = Mock(spec=[
                "prep_send_transaction",
                "delivered_txn",
                "get_received_txn_response",
                "set_received_txn_response",
    
    matrix.org's avatar
    matrix.org committed
            ])
            self.mock_persistence.get_received_txn_response.return_value = (
    
    Erik Johnston's avatar
    Erik Johnston committed
                defer.succeed(None)
    
    
            retry_timings_res = {
                "destination": "",
                "retry_last_ts": 0,
                "retry_interval": 0,
            }
    
            self.mock_persistence.get_destination_retry_timings.return_value = (
    
                defer.succeed(retry_timings_res)
    
            self.mock_persistence.get_auth_chain.return_value = []
    
    matrix.org's avatar
    matrix.org committed
            self.clock = MockClock()
    
            hs = yield setup_test_homeserver(
    
    Erik Johnston's avatar
    Erik Johnston committed
                resource_for_federation=self.mock_resource,
                http_client=self.mock_http_client,
                datastore=self.mock_persistence,
                clock=self.clock,
                keyring=Mock(),
    
    matrix.org's avatar
    matrix.org committed
            )
            self.federation = initialize_http_replication(hs)
            self.distributor = hs.get_distributor()
    
        @defer.inlineCallbacks
        def test_get_state(self):
    
    Erik Johnston's avatar
    Erik Johnston committed
            mock_handler = Mock(spec=[
                "get_state_for_pdu",
            ])
    
            self.federation.set_handler(mock_handler)
    
            mock_handler.get_state_for_pdu.return_value = defer.succeed([])
    
    matrix.org's avatar
    matrix.org committed
    
            # Empty context initially
    
    Erik Johnston's avatar
    Erik Johnston committed
            (code, response) = yield self.mock_resource.trigger(
                "GET",
                "/_matrix/federation/v1/state/my-context/",
                None
            )
    
    matrix.org's avatar
    matrix.org committed
            self.assertEquals(200, code)
            self.assertFalse(response["pdus"])
    
            # Now lets give the context some state
    
    Erik Johnston's avatar
    Erik Johnston committed
            mock_handler.get_state_for_pdu.return_value = (
    
    matrix.org's avatar
    matrix.org committed
                defer.succeed([
                    make_pdu(
    
    Erik Johnston's avatar
    Erik Johnston committed
                        event_id="the-pdu-id",
    
    matrix.org's avatar
    matrix.org committed
                        origin="red",
    
    Mark Haines's avatar
    Mark Haines committed
                        user_id="@a:red",
    
    Erik Johnston's avatar
    Erik Johnston committed
                        room_id="my-context",
                        type="m.topic",
                        origin_server_ts=123456789000,
    
    matrix.org's avatar
    matrix.org committed
                        depth=1,
    
    Erik Johnston's avatar
    Erik Johnston committed
                        content={"topic": "The topic"},
    
    matrix.org's avatar
    matrix.org committed
                        state_key="",
                        power_level=1000,
    
    Erik Johnston's avatar
    Erik Johnston committed
                        prev_state="last-pdu-id",
    
    Erik Johnston's avatar
    Erik Johnston committed
            (code, response) = yield self.mock_resource.trigger(
                "GET",
                "/_matrix/federation/v1/state/my-context/",
                None
            )
    
    matrix.org's avatar
    matrix.org committed
            self.assertEquals(200, code)
            self.assertEquals(1, len(response["pdus"]))
    
        @defer.inlineCallbacks
        def test_get_pdu(self):
    
    Erik Johnston's avatar
    Erik Johnston committed
            mock_handler = Mock(spec=[
                "get_persisted_pdu",
            ])
    
            self.federation.set_handler(mock_handler)
    
            mock_handler.get_persisted_pdu.return_value = (
    
    matrix.org's avatar
    matrix.org committed
                defer.succeed(None)
            )
    
    
    Erik Johnston's avatar
    Erik Johnston committed
            (code, response) = yield self.mock_resource.trigger(
                "GET",
                "/_matrix/federation/v1/event/abc123def456/",
                None
            )
    
    matrix.org's avatar
    matrix.org committed
            self.assertEquals(404, code)
    
            # Now insert such a PDU
    
    Erik Johnston's avatar
    Erik Johnston committed
            mock_handler.get_persisted_pdu.return_value = (
    
    matrix.org's avatar
    matrix.org committed
                defer.succeed(
                    make_pdu(
    
    Erik Johnston's avatar
    Erik Johnston committed
                        event_id="abc123def456",
    
    matrix.org's avatar
    matrix.org committed
                        origin="red",
    
    Mark Haines's avatar
    Mark Haines committed
                        user_id="@a:red",
    
    Erik Johnston's avatar
    Erik Johnston committed
                        room_id="my-context",
                        type="m.text",
                        origin_server_ts=123456789001,
    
    matrix.org's avatar
    matrix.org committed
                        depth=1,
    
    Erik Johnston's avatar
    Erik Johnston committed
                        content={"text": "Here is the message"},
    
    Erik Johnston's avatar
    Erik Johnston committed
            (code, response) = yield self.mock_resource.trigger(
                "GET",
                "/_matrix/federation/v1/event/abc123def456/",
                None
            )
    
    matrix.org's avatar
    matrix.org committed
            self.assertEquals(200, code)
            self.assertEquals(1, len(response["pdus"]))
    
    Erik Johnston's avatar
    Erik Johnston committed
            self.assertEquals("m.text", response["pdus"][0]["type"])
    
    matrix.org's avatar
    matrix.org committed
    
        @defer.inlineCallbacks
        def test_send_pdu(self):
            self.mock_http_client.put_json.return_value = defer.succeed(
    
    Erik Johnston's avatar
    Erik Johnston committed
                (200, "OK")
    
    Erik Johnston's avatar
    Erik Johnston committed
            pdu = make_pdu(
    
    Erik Johnston's avatar
    Erik Johnston committed
                event_id="abc123def456",
                origin="red",
    
    Mark Haines's avatar
    Mark Haines committed
                user_id="@a:red",
    
    Erik Johnston's avatar
    Erik Johnston committed
                room_id="my-context",
                type="m.text",
                origin_server_ts=123456789001,
                depth=1,
                content={"text": "Here is the message"},
    
    Erik Johnston's avatar
    Erik Johnston committed
            yield self.federation.send_pdu(pdu, ["remote"])
    
    matrix.org's avatar
    matrix.org committed
    
            self.mock_http_client.put_json.assert_called_with(
    
    Erik Johnston's avatar
    Erik Johnston committed
                "remote",
                path="/_matrix/federation/v1/send/1000000/",
                data={
                    "origin_server_ts": 1000000,
                    "origin": "test",
                    "pdus": [
    
                        pdu.get_pdu_json(),
    
    Erik Johnston's avatar
    Erik Johnston committed
                    ],
                    'pdu_failures': [],
                },
                json_data_callback=ANY,
    
    Erik Johnston's avatar
    Erik Johnston committed
                long_retries=True,
    
    matrix.org's avatar
    matrix.org committed
            )
    
        @defer.inlineCallbacks
        def test_send_edu(self):
            self.mock_http_client.put_json.return_value = defer.succeed(
    
    Erik Johnston's avatar
    Erik Johnston committed
                (200, "OK")
    
    matrix.org's avatar
    matrix.org committed
            )
    
            yield self.federation.send_edu(
    
    Erik Johnston's avatar
    Erik Johnston committed
                destination="remote",
                edu_type="m.test",
                content={"testing": "content here"},
    
    matrix.org's avatar
    matrix.org committed
            )
    
            # MockClock ensures we can guess these timestamps
            self.mock_http_client.put_json.assert_called_with(
    
    Erik Johnston's avatar
    Erik Johnston committed
                "remote",
                path="/_matrix/federation/v1/send/1000000/",
                data={
                    "origin": "test",
                    "origin_server_ts": 1000000,
                    "pdus": [],
                    "edus": [
                        {
                            "edu_type": "m.test",
                            "content": {"testing": "content here"},
                        }
                    ],
                    'pdu_failures': [],
                },
                json_data_callback=ANY,
    
    Erik Johnston's avatar
    Erik Johnston committed
                long_retries=True,
    
    matrix.org's avatar
    matrix.org committed
    
        @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)
    
    
    Erik Johnston's avatar
    Erik Johnston committed
            yield self.mock_resource.trigger(
                "PUT",
                "/_matrix/federation/v1/send/1001000/",
                """{
                    "origin": "remote",
                    "origin_server_ts": 1001000,
                    "pdus": [],
                    "edus": [
                        {
                            "origin": "remote",
                            "destination": "test",
                            "edu_type": "m.test",
                            "content": {"testing": "reply here"}
                        }
                    ]
                }"""
            )
    
    matrix.org's avatar
    matrix.org committed
    
            recv_observer.assert_called_with(
    
    Erik Johnston's avatar
    Erik Johnston committed
                "remote", {"testing": "reply here"}
    
    
        @defer.inlineCallbacks
        def test_send_query(self):
            self.mock_http_client.get_json.return_value = defer.succeed(
                {"your": "response"}
            )
    
            response = yield self.federation.make_query(
                destination="remote",
                query_type="a-question",
    
            )
    
            self.assertEquals({"your": "response"}, response)
    
            self.mock_http_client.get_json.assert_called_with(
                destination="remote",
    
                path="/_matrix/federation/v1/query/a-question",
    
                args={"one": "1", "two": "2"},
                retry_on_dns_fail=True,
    
            )
    
        @defer.inlineCallbacks
        def test_recv_query(self):
            recv_handler = Mock()
            recv_handler.return_value = defer.succeed({"another": "response"})
    
            self.federation.register_query_handler("a-question", recv_handler)
    
    
    Erik Johnston's avatar
    Erik Johnston committed
            code, response = yield self.mock_resource.trigger(
                "GET",
                "/_matrix/federation/v1/query/a-question?three=3&four=4",
                None
            )
    
    
            self.assertEquals(200, code)
            self.assertEquals({"another": "response"}, response)
    
            recv_handler.assert_called_with(
                {"three": "3", "four": "4"}
            )