Skip to content
Snippets Groups Projects
test_room.py 10.4 KiB
Newer Older
  • Learn to ignore specific revisions
  • matrix.org's avatar
    matrix.org committed
    # -*- coding: utf-8 -*-
    
    #
    # 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
    
    from twisted.internet import defer
    
    matrix.org's avatar
    matrix.org committed
    
    from synapse.api.events.room import (
    
    Erik Johnston's avatar
    Erik Johnston committed
        RoomMemberEvent,
    
    Erik Johnston's avatar
    Erik Johnston committed
    from synapse.api.constants import EventTypes, Membership
    
    matrix.org's avatar
    matrix.org committed
    from synapse.handlers.room import RoomMemberHandler, RoomCreationHandler
    from synapse.handlers.profile import ProfileHandler
    from synapse.server import HomeServer
    
    from ..utils import MockKey
    
    matrix.org's avatar
    matrix.org committed
    
    from mock import Mock, NonCallableMock
    
    
    class RoomMemberHandlerTestCase(unittest.TestCase):
    
        def setUp(self):
    
            self.mock_config = NonCallableMock()
            self.mock_config.signing_key = [MockKey()]
    
    matrix.org's avatar
    matrix.org committed
            self.hostname = "red"
            hs = HomeServer(
                self.hostname,
                db_pool=None,
    
                ratelimiter=NonCallableMock(spec_set=[
                    "send_message",
                ]),
    
    matrix.org's avatar
    matrix.org committed
                datastore=NonCallableMock(spec_set=[
    
    matrix.org's avatar
    matrix.org committed
                    "get_room_member",
                    "get_room",
                    "store_room",
    
                    "get_latest_events_in_room",
    
    matrix.org's avatar
    matrix.org committed
                ]),
    
                resource_for_federation=NonCallableMock(),
    
    matrix.org's avatar
    matrix.org committed
                http_client=NonCallableMock(spec_set=[]),
                notifier=NonCallableMock(spec_set=["on_new_room_event"]),
                handlers=NonCallableMock(spec_set=[
                    "room_member_handler",
                    "profile_handler",
    
                    "federation_handler",
    
    matrix.org's avatar
    matrix.org committed
                ]),
    
                auth=NonCallableMock(spec_set=[
                    "check",
                    "add_auth_events",
                    "check_host_in_room",
                ]),
    
    Erik Johnston's avatar
    Erik Johnston committed
                state_handler=NonCallableMock(spec_set=[
    
                    "annotate_context_with_state",
    
                    "get_current_state",
    
    Erik Johnston's avatar
    Erik Johnston committed
                ]),
    
                config=self.mock_config,
    
            self.federation = NonCallableMock(spec_set=[
                "handle_new_event",
    
    Erik Johnston's avatar
    Erik Johnston committed
                "send_invite",
    
                "get_state_for_room",
            ])
    
    
    matrix.org's avatar
    matrix.org committed
            self.datastore = hs.get_datastore()
            self.handlers = hs.get_handlers()
            self.notifier = hs.get_notifier()
            self.state_handler = hs.get_state_handler()
            self.distributor = hs.get_distributor()
    
            self.auth = hs.get_auth()
    
    matrix.org's avatar
    matrix.org committed
            self.hs = hs
    
    
            self.handlers.federation_handler = self.federation
    
    
    matrix.org's avatar
    matrix.org committed
            self.handlers.room_member_handler = RoomMemberHandler(self.hs)
            self.handlers.profile_handler = ProfileHandler(self.hs)
            self.room_member_handler = self.handlers.room_member_handler
    
    
            self.ratelimiter = hs.get_ratelimiter()
            self.ratelimiter.send_message.return_value = (True, 0)
    
    matrix.org's avatar
    matrix.org committed
        @defer.inlineCallbacks
        def test_invite(self):
            room_id = "!foo:red"
            user_id = "@bob:red"
            target_user_id = "@red:blue"
            content = {"membership": Membership.INVITE}
    
    
            builder = self.hs.get_event_builder_factory().new({
                "type": RoomMemberEvent.TYPE,
                "sender": user_id,
                "state_key": target_user_id,
                "room_id": room_id,
                "content": content,
            })
    
            self.datastore.get_latest_events_in_room.return_value = (
                defer.succeed([])
    
            def annotate(_, ctx):
                ctx.current_state = {
                    (RoomMemberEvent.TYPE, "@alice:green"): self._create_member(
                        user_id="@alice:green",
                        room_id=room_id,
                    ),
                    (RoomMemberEvent.TYPE, "@bob:red"): self._create_member(
                        user_id="@bob:red",
                        room_id=room_id,
                    ),
                }
    
                return defer.succeed(True)
    
            self.state_handler.annotate_context_with_state.side_effect = annotate
    
            def add_auth(_, ctx):
                ctx.auth_events = ctx.current_state[
                    (RoomMemberEvent.TYPE, "@bob:red")
                ]
    
                return defer.succeed(True)
            self.auth.add_auth_events.side_effect = add_auth
    
            def send_invite(domain, event):
                return defer.succeed(event)
    
            self.federation.send_invite.side_effect = send_invite
    
            room_handler = self.room_member_handler
            event, context = yield room_handler._create_new_client_event(
                builder
    
            yield room_handler.change_membership(event, context)
    
            self.state_handler.annotate_context_with_state.assert_called_once_with(
                builder, context
            )
    
            self.auth.add_auth_events.assert_called_once_with(
                builder, context
            )
    
            self.federation.send_invite.assert_called_once_with(
                "blue", event,
    
            self.datastore.persist_event.assert_called_once_with(
    
                event, context=context,
    
    matrix.org's avatar
    matrix.org committed
            )
            self.notifier.on_new_room_event.assert_called_once_with(
    
                event, extra_users=[self.hs.parse_userid(target_user_id)]
    
    matrix.org's avatar
    matrix.org committed
            self.assertFalse(self.datastore.get_room.called)
            self.assertFalse(self.datastore.store_room.called)
            self.assertFalse(self.federation.get_state_for_room.called)
    
        @defer.inlineCallbacks
        def test_simple_join(self):
            room_id = "!foo:red"
            user_id = "@bob:red"
            user = self.hs.parse_userid(user_id)
    
    
            join_signal_observer = Mock()
            self.distributor.observe("user_joined_room", join_signal_observer)
    
            builder = self.hs.get_event_builder_factory().new({
                "type": RoomMemberEvent.TYPE,
                "sender": user_id,
                "state_key": user_id,
                "room_id": room_id,
                "content": {"membership": Membership.JOIN},
            })
    
            self.datastore.get_latest_events_in_room.return_value = (
                defer.succeed([])
            )
    
            def annotate(_, ctx):
                ctx.current_state = {
                    (RoomMemberEvent.TYPE, "@bob:red"): self._create_member(
                        user_id="@bob:red",
                        room_id=room_id,
                        membership=Membership.INVITE
                    ),
                }
    
                return defer.succeed(True)
    
            self.state_handler.annotate_context_with_state.side_effect = annotate
    
            def add_auth(_, ctx):
                ctx.auth_events = ctx.current_state[
                    (RoomMemberEvent.TYPE, "@bob:red")
                ]
    
                return defer.succeed(True)
            self.auth.add_auth_events.side_effect = add_auth
    
            room_handler = self.room_member_handler
            event, context = yield room_handler._create_new_client_event(
                builder
            )
    
    matrix.org's avatar
    matrix.org committed
            # Actual invocation
    
            yield room_handler.change_membership(event, context)
    
            self.federation.handle_new_event.assert_called_once_with(
    
                event, None, destinations=set()
    
            self.datastore.persist_event.assert_called_once_with(
    
                event, context=context
    
    matrix.org's avatar
    matrix.org committed
            )
            self.notifier.on_new_room_event.assert_called_once_with(
    
    Erik Johnston's avatar
    Erik Johnston committed
                event, extra_users=[user]
            )
    
    matrix.org's avatar
    matrix.org committed
    
            join_signal_observer.assert_called_with(
    
    Erik Johnston's avatar
    Erik Johnston committed
                user=user, room_id=room_id
            )
    
        def _create_member(self, user_id, room_id, membership=Membership.JOIN):
            builder = self.hs.get_event_builder_factory().new({
                "type": RoomMemberEvent.TYPE,
                "sender": user_id,
                "state_key": user_id,
                "room_id": room_id,
                "content": {"membership": membership},
            })
    
            return builder.build()
    
    matrix.org's avatar
    matrix.org committed
    
    class RoomCreationTest(unittest.TestCase):
    
        def setUp(self):
            self.hostname = "red"
    
    Erik Johnston's avatar
    Erik Johnston committed
    
            self.mock_config = NonCallableMock()
            self.mock_config.signing_key = [MockKey()]
    
    
    matrix.org's avatar
    matrix.org committed
            hs = HomeServer(
                self.hostname,
                db_pool=None,
                datastore=NonCallableMock(spec_set=[
                    "store_room",
    
                    "snapshot_room",
    
                    "persist_event",
                    "get_joined_hosts_for_room",
    
    matrix.org's avatar
    matrix.org committed
                ]),
                http_client=NonCallableMock(spec_set=[]),
                notifier=NonCallableMock(spec_set=["on_new_room_event"]),
                handlers=NonCallableMock(spec_set=[
                    "room_creation_handler",
    
    Erik Johnston's avatar
    Erik Johnston committed
                    "message_handler",
    
    matrix.org's avatar
    matrix.org committed
                ]),
    
    Erik Johnston's avatar
    Erik Johnston committed
                auth=NonCallableMock(spec_set=["check", "add_auth_events"]),
    
                ratelimiter=NonCallableMock(spec_set=[
                    "send_message",
                ]),
    
    Erik Johnston's avatar
    Erik Johnston committed
                config=self.mock_config,
    
            self.federation = NonCallableMock(spec_set=[
                "handle_new_event",
            ])
    
    
    matrix.org's avatar
    matrix.org committed
            self.handlers = hs.get_handlers()
    
    Erik Johnston's avatar
    Erik Johnston committed
            self.handlers.room_creation_handler = RoomCreationHandler(hs)
    
    matrix.org's avatar
    matrix.org committed
            self.room_creation_handler = self.handlers.room_creation_handler
    
    
    Erik Johnston's avatar
    Erik Johnston committed
            self.message_handler = self.handlers.message_handler
    
            self.ratelimiter = hs.get_ratelimiter()
            self.ratelimiter.send_message.return_value = (True, 0)
    
    
    matrix.org's avatar
    matrix.org committed
        @defer.inlineCallbacks
        def test_room_creation(self):
            user_id = "@foo:red"
            room_id = "!bobs_room:red"
            config = {"visibility": "private"}
    
            yield self.room_creation_handler.create_room(
                user_id=user_id,
                room_id=room_id,
                config=config,
            )
    
    
    Erik Johnston's avatar
    Erik Johnston committed
            self.assertTrue(self.message_handler.handle_event.called)
    
            event_dicts = [
                e[0][0] for e in self.message_handler.handle_event.call_args_list
            ]
    
    Erik Johnston's avatar
    Erik Johnston committed
            self.assertTrue(len(event_dicts) > 3)
    
    Erik Johnston's avatar
    Erik Johnston committed
            self.assertDictContainsSubset(
                {
                    "type": EventTypes.Create,
                    "sender": user_id,
                    "room_id": room_id,
                },
                event_dicts[0]
            )
    
            self.assertEqual(user_id, event_dicts[0]["content"]["creator"])
    
    Erik Johnston's avatar
    Erik Johnston committed
            self.assertDictContainsSubset(
                {
                    "type": EventTypes.Member,
                    "sender": user_id,
                    "room_id": room_id,
                    "state_key": user_id,
                },
                event_dicts[1]
            )
    
            self.assertEqual(
                Membership.JOIN,
                event_dicts[1]["content"]["membership"]
            )