123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289 |
- # Copyright 2014 OpenMarket Ltd
- #
- # 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.
- # trial imports
- from twisted.internet import defer
- from tests import unittest
- # python imports
- from mock import Mock, ANY
- from ..utils import MockHttpResource, MockClock, MockKey
- 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
- 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 FederationTestCase(unittest.TestCase):
- def setUp(self):
- self.mock_resource = MockHttpResource()
- self.mock_http_client = Mock(spec=[
- "get_json",
- "put_json",
- ])
- self.mock_persistence = Mock(spec=[
- "get_current_state_for_context",
- "get_pdu",
- "persist_event",
- "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.mock_config = Mock()
- self.mock_config.signing_key = [MockKey()]
- self.clock = MockClock()
- hs = HomeServer("test",
- resource_for_federation=self.mock_resource,
- http_client=self.mock_http_client,
- db_pool=None,
- datastore=self.mock_persistence,
- clock=self.clock,
- config=self.mock_config,
- keyring=Mock(),
- )
- 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_resource.trigger("GET",
- "/_matrix/federation/v1/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_resource.trigger("GET",
- "/_matrix/federation/v1/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_resource.trigger("GET",
- "/_matrix/federation/v1/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_resource.trigger("GET",
- "/_matrix/federation/v1/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",
- origin_server_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="/_matrix/federation/v1/send/1000000/",
- data={
- "origin_server_ts": 1000000,
- "origin": "test",
- "pdus": [
- {
- "origin": "red",
- "pdu_id": "abc123def456",
- "prev_pdus": [],
- "origin_server_ts": 123456789002,
- "context": "my-context",
- "pdu_type": "m.test",
- "is_state": False,
- "content": {"testing": "content here"},
- "depth": 1,
- },
- ]
- },
- json_data_callback=ANY,
- )
- @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="/_matrix/federation/v1/send/1000000/",
- data={
- "origin": "test",
- "origin_server_ts": 1000000,
- "pdus": [],
- "edus": [
- {
- # TODO: SYN-103: Remove "origin" and "destination"
- "origin": "test",
- "destination": "remote",
- "edu_type": "m.test",
- "content": {"testing": "content here"},
- }
- ],
- },
- json_data_callback=ANY,
- )
- @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_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"}
- }
- ]
- }""")
- recv_observer.assert_called_with(
- "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",
- args={"one": "1", "two": "2"},
- )
- 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)
- 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"}
- )
|