Skip to content
Snippets Groups Projects
test_presence.py 11.6 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
    """Tests REST events for /presence paths."""
    
    
    matrix.org's avatar
    matrix.org committed
    from twisted.internet import defer
    
    from mock import Mock
    
    
    from ....utils import MockHttpResource, MockKey
    
    matrix.org's avatar
    matrix.org committed
    
    from synapse.api.constants import PresenceState
    
    from synapse.handlers.presence import PresenceHandler
    
    matrix.org's avatar
    matrix.org committed
    from synapse.server import HomeServer
    
    from synapse.rest.client.v1 import presence
    from synapse.rest.client.v1 import events
    
    matrix.org's avatar
    matrix.org committed
    
    
    OFFLINE = PresenceState.OFFLINE
    
    matrix.org's avatar
    matrix.org committed
    ONLINE = PresenceState.ONLINE
    
    
    myid = "@apple:test"
    
    class JustPresenceHandlers(object):
        def __init__(self, hs):
            self.presence_handler = PresenceHandler(hs)
    
    
    
    matrix.org's avatar
    matrix.org committed
    class PresenceStateTestCase(unittest.TestCase):
    
        def setUp(self):
    
            self.mock_resource = MockHttpResource(prefix=PATH_PREFIX)
    
            self.mock_config = Mock()
            self.mock_config.signing_key = [MockKey()]
    
    matrix.org's avatar
    matrix.org committed
            hs = HomeServer("test",
                db_pool=None,
    
                datastore=Mock(spec=[
                    "get_presence_state",
                    "set_presence_state",
    
    matrix.org's avatar
    matrix.org committed
                http_client=None,
    
                resource_for_client=self.mock_resource,
                resource_for_federation=self.mock_resource,
    
                config=self.mock_config,
    
            hs.handlers = JustPresenceHandlers(hs)
    
            self.datastore = hs.get_datastore()
    
            def get_presence_list(*a, **kw):
                return defer.succeed([])
            self.datastore.get_presence_list = get_presence_list
    
    matrix.org's avatar
    matrix.org committed
    
            def _get_user_by_token(token=None):
    
                return {
                    "user": hs.parse_userid(myid),
                    "admin": False,
                    "device_id": None,
                }
    
    matrix.org's avatar
    matrix.org committed
    
            hs.get_auth().get_user_by_token = _get_user_by_token
    
    
            room_member_handler = hs.handlers.room_member_handler = Mock(
                spec=[
                    "get_rooms_for_user",
                ]
            )
    
            def get_rooms_for_user(user):
                return defer.succeed([])
            room_member_handler.get_rooms_for_user = get_rooms_for_user
    
            presence.register_servlets(hs, self.mock_resource)
    
    matrix.org's avatar
    matrix.org committed
    
            self.u_apple = hs.parse_userid(myid)
    
        @defer.inlineCallbacks
        def test_get_my_status(self):
    
            mocked_get = self.datastore.get_presence_state
    
    matrix.org's avatar
    matrix.org committed
            mocked_get.return_value = defer.succeed(
    
            (code, response) = yield self.mock_resource.trigger("GET",
    
    matrix.org's avatar
    matrix.org committed
                    "/presence/%s/status" % (myid), None)
    
            self.assertEquals(200, code)
    
    Paul "LeoNerd" Evans's avatar
    Paul "LeoNerd" Evans committed
                {"presence": ONLINE, "status_msg": "Available"},
    
    matrix.org's avatar
    matrix.org committed
    
        @defer.inlineCallbacks
        def test_set_my_status(self):
    
            mocked_set = self.datastore.set_presence_state
            mocked_set.return_value = defer.succeed({"state": OFFLINE})
    
            (code, response) = yield self.mock_resource.trigger("PUT",
    
    matrix.org's avatar
    matrix.org committed
                    "/presence/%s/status" % (myid),
    
                    '{"presence": "unavailable", "status_msg": "Away"}')
    
    matrix.org's avatar
    matrix.org committed
    
            self.assertEquals(200, code)
    
    Paul "LeoNerd" Evans's avatar
    Paul "LeoNerd" Evans committed
                {"state": UNAVAILABLE, "status_msg": "Away"}
            )
    
    matrix.org's avatar
    matrix.org committed
    
    
    class PresenceListTestCase(unittest.TestCase):
    
        def setUp(self):
    
            self.mock_resource = MockHttpResource(prefix=PATH_PREFIX)
    
            self.mock_config = Mock()
            self.mock_config.signing_key = [MockKey()]
    
    matrix.org's avatar
    matrix.org committed
    
            hs = HomeServer("test",
                db_pool=None,
    
                datastore=Mock(spec=[
                    "has_presence_state",
                    "get_presence_state",
                    "allow_presence_visible",
                    "is_presence_visible",
                    "add_presence_list_pending",
                    "set_presence_list_accepted",
                    "del_presence_list",
                    "get_presence_list",
    
    matrix.org's avatar
    matrix.org committed
                http_client=None,
    
                resource_for_federation=self.mock_resource,
                config=self.mock_config,
    
            hs.handlers = JustPresenceHandlers(hs)
    
            self.datastore = hs.get_datastore()
    
            def has_presence_state(user_localpart):
                return defer.succeed(
                    user_localpart in ("apple", "banana",)
                )
            self.datastore.has_presence_state = has_presence_state
    
    matrix.org's avatar
    matrix.org committed
    
            def _get_user_by_token(token=None):
    
                return {
                    "user": hs.parse_userid(myid),
                    "admin": False,
                    "device_id": None,
                }
    
            room_member_handler = hs.handlers.room_member_handler = Mock(
                spec=[
                    "get_rooms_for_user",
                ]
            )
    
            hs.get_auth().get_user_by_token = _get_user_by_token
    
            presence.register_servlets(hs, self.mock_resource)
    
    matrix.org's avatar
    matrix.org committed
    
            self.u_apple = hs.parse_userid("@apple:test")
            self.u_banana = hs.parse_userid("@banana:test")
    
        @defer.inlineCallbacks
        def test_get_my_list(self):
    
            self.datastore.get_presence_list.return_value = defer.succeed(
                [{"observed_user_id": "@banana:test"}],
    
            (code, response) = yield self.mock_resource.trigger("GET",
    
    matrix.org's avatar
    matrix.org committed
    
            self.assertEquals(200, code)
    
    Paul "LeoNerd" Evans's avatar
    Paul "LeoNerd" Evans committed
                {"user_id": "@banana:test", "presence": OFFLINE},
    
    
            self.datastore.get_presence_list.assert_called_with(
                "apple", accepted=True
            )
    
    matrix.org's avatar
    matrix.org committed
    
        @defer.inlineCallbacks
        def test_invite(self):
    
            self.datastore.add_presence_list_pending.return_value = (
                defer.succeed(())
            )
            self.datastore.is_presence_visible.return_value = defer.succeed(
                True
            )
    
            (code, response) = yield self.mock_resource.trigger("POST",
    
    matrix.org's avatar
    matrix.org committed
    
            self.assertEquals(200, code)
    
    
            self.datastore.add_presence_list_pending.assert_called_with(
                "apple", "@banana:test"
            )
            self.datastore.set_presence_list_accepted.assert_called_with(
                "apple", "@banana:test"
            )
    
    matrix.org's avatar
    matrix.org committed
    
        @defer.inlineCallbacks
        def test_drop(self):
    
            self.datastore.del_presence_list.return_value = (
                defer.succeed(())
            )
    
            (code, response) = yield self.mock_resource.trigger("POST",
    
    matrix.org's avatar
    matrix.org committed
    
            self.assertEquals(200, code)
    
    
            self.datastore.del_presence_list.assert_called_with(
                "apple", "@banana:test"
            )
    
    matrix.org's avatar
    matrix.org committed
    
    
    class PresenceEventStreamTestCase(unittest.TestCase):
        def setUp(self):
    
            self.mock_resource = MockHttpResource(prefix=PATH_PREFIX)
    
            self.mock_config = Mock()
            self.mock_config.signing_key = [MockKey()]
    
    
    matrix.org's avatar
    matrix.org committed
            # HIDEOUS HACKERY
            # TODO(paul): This should be injected in via the HomeServer DI system
    
            )
    
            old_SOURCE_TYPES = EventSources.SOURCE_TYPES
            def tearDown():
                EventSources.SOURCE_TYPES = old_SOURCE_TYPES
            self.tearDown = tearDown
    
            EventSources.SOURCE_TYPES = {
                k: NullSource for k in old_SOURCE_TYPES.keys()
            }
    
            EventSources.SOURCE_TYPES["presence"] = PresenceEventSource
    
    matrix.org's avatar
    matrix.org committed
    
            hs = HomeServer("test",
                db_pool=None,
                http_client=None,
    
                resource_for_client=self.mock_resource,
                resource_for_federation=self.mock_resource,
    
    matrix.org's avatar
    matrix.org committed
                datastore=Mock(spec=[
                    "set_presence_state",
                    "get_presence_list",
                ]),
                clock=Mock(spec=[
                    "call_later",
                    "cancel_call_later",
                    "time_msec",
                ]),
    
                config=self.mock_config,
    
    matrix.org's avatar
    matrix.org committed
            )
    
            hs.get_clock().time_msec.return_value = 1000000
    
            def _get_user_by_req(req=None):
                return hs.parse_userid(myid)
    
            hs.get_auth().get_user_by_req = _get_user_by_req
    
    
            presence.register_servlets(hs, self.mock_resource)
            events.register_servlets(hs, self.mock_resource)
    
            hs.handlers.room_member_handler = Mock(spec=[])
    
            self.room_members = []
    
            def get_rooms_for_user(user):
                if user in self.room_members:
                    return ["a-room"]
                else:
                    return []
            hs.handlers.room_member_handler.get_rooms_for_user = get_rooms_for_user
    
    matrix.org's avatar
    matrix.org committed
    
            self.mock_datastore = hs.get_datastore()
    
    
            def get_profile_displayname(user_id):
                return defer.succeed("Frank")
            self.mock_datastore.get_profile_displayname = get_profile_displayname
    
            def get_profile_avatar_url(user_id):
                return defer.succeed(None)
            self.mock_datastore.get_profile_avatar_url = get_profile_avatar_url
    
    
            def user_rooms_intersect(user_list):
                room_member_ids = map(lambda u: u.to_string(), self.room_members)
    
                shared = all(map(lambda i: i in room_member_ids, user_list))
                return defer.succeed(shared)
            self.mock_datastore.user_rooms_intersect = user_rooms_intersect
    
            def get_joined_hosts_for_room(room_id):
                return []
            self.mock_datastore.get_joined_hosts_for_room = get_joined_hosts_for_room
    
    
    matrix.org's avatar
    matrix.org committed
            self.presence = hs.get_handlers().presence_handler
    
            self.u_apple = hs.parse_userid("@apple:test")
            self.u_banana = hs.parse_userid("@banana:test")
    
        @defer.inlineCallbacks
        def test_shortpoll(self):
    
            self.room_members = [self.u_apple, self.u_banana]
    
    
    matrix.org's avatar
    matrix.org committed
            self.mock_datastore.set_presence_state.return_value = defer.succeed(
    
    Paul "LeoNerd" Evans's avatar
    Paul "LeoNerd" Evans committed
                {"state": ONLINE}
            )
    
    matrix.org's avatar
    matrix.org committed
            self.mock_datastore.get_presence_list.return_value = defer.succeed(
    
            (code, response) = yield self.mock_resource.trigger("GET",
    
    matrix.org's avatar
    matrix.org committed
                    "/events?timeout=0", None)
    
            self.assertEquals(200, code)
    
            # We've forced there to be only one data stream so the tokens will
            # all be ours
    
            # I'll already get my own presence state change
    
            self.assertEquals({"start": "0_1_0", "end": "0_1_0", "chunk": []},
                response
            )
    
    matrix.org's avatar
    matrix.org committed
    
            self.mock_datastore.set_presence_state.return_value = defer.succeed(
    
    Paul "LeoNerd" Evans's avatar
    Paul "LeoNerd" Evans committed
                {"state": ONLINE}
            )
    
    matrix.org's avatar
    matrix.org committed
            self.mock_datastore.get_presence_list.return_value = defer.succeed(
    
    matrix.org's avatar
    matrix.org committed
    
            yield self.presence.set_state(self.u_banana, self.u_banana,
    
            (code, response) = yield self.mock_resource.trigger("GET",
    
    matrix.org's avatar
    matrix.org committed
    
            self.assertEquals(200, code)
    
            self.assertEquals({"start": "0_1_0", "end": "0_2_0", "chunk": [
    
    matrix.org's avatar
    matrix.org committed
                {"type": "m.presence",
    
    matrix.org's avatar
    matrix.org committed
            ]}, response)