Newer
Older
Matthew Hodgson
committed
# Copyright 2014 OpenMarket Ltd
Matthew Hodgson
committed
#
# 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.
"""Tests REST events for /presence paths."""
Paul "LeoNerd" Evans
committed
from tests import unittest
from twisted.internet import defer
from mock import Mock
from ....utils import MockHttpResource, MockKey
from synapse.api.constants import PresenceState
Paul "LeoNerd" Evans
committed
from synapse.handlers.presence import PresenceHandler
from synapse.rest.client.v1 import presence
from synapse.rest.client.v1 import events
Paul "LeoNerd" Evans
committed
UNAVAILABLE = PresenceState.UNAVAILABLE
ONLINE = PresenceState.ONLINE
myid = "@apple:test"
Matthew Hodgson
committed
PATH_PREFIX = "/_matrix/client/api/v1"
Paul "LeoNerd" Evans
committed
class JustPresenceHandlers(object):
def __init__(self, hs):
self.presence_handler = PresenceHandler(hs)
class PresenceStateTestCase(unittest.TestCase):
def setUp(self):
Paul "LeoNerd" Evans
committed
self.mock_resource = MockHttpResource(prefix=PATH_PREFIX)
self.mock_config = Mock()
self.mock_config.signing_key = [MockKey()]
Paul "LeoNerd" Evans
committed
datastore=Mock(spec=[
"get_presence_state",
"set_presence_state",
"insert_client_ip",
Paul "LeoNerd" Evans
committed
]),
Paul "LeoNerd" Evans
committed
resource_for_client=self.mock_resource,
resource_for_federation=self.mock_resource,
Paul "LeoNerd" Evans
committed
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
return {
"user": hs.parse_userid(myid),
"admin": False,
"device_id": None,
}
hs.get_auth().get_user_by_token = _get_user_by_token
Paul "LeoNerd" Evans
committed
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)
self.u_apple = hs.parse_userid(myid)
@defer.inlineCallbacks
def test_get_my_status(self):
Paul "LeoNerd" Evans
committed
mocked_get = self.datastore.get_presence_state
Paul "LeoNerd" Evans
committed
{"state": ONLINE, "status_msg": "Available"}
)
Paul "LeoNerd" Evans
committed
(code, response) = yield self.mock_resource.trigger("GET",
"/presence/%s/status" % (myid), None)
self.assertEquals(200, code)
Paul "LeoNerd" Evans
committed
self.assertEquals(
Paul "LeoNerd" Evans
committed
response
)
Paul "LeoNerd" Evans
committed
mocked_get.assert_called_with("apple")
@defer.inlineCallbacks
def test_set_my_status(self):
Paul "LeoNerd" Evans
committed
mocked_set = self.datastore.set_presence_state
mocked_set.return_value = defer.succeed({"state": OFFLINE})
Paul "LeoNerd" Evans
committed
(code, response) = yield self.mock_resource.trigger("PUT",
Paul "LeoNerd" Evans
committed
'{"presence": "unavailable", "status_msg": "Away"}')
Paul "LeoNerd" Evans
committed
mocked_set.assert_called_with("apple",
{"state": UNAVAILABLE, "status_msg": "Away"}
)
class PresenceListTestCase(unittest.TestCase):
def setUp(self):
Paul "LeoNerd" Evans
committed
self.mock_resource = MockHttpResource(prefix=PATH_PREFIX)
self.mock_config = Mock()
self.mock_config.signing_key = [MockKey()]
Paul "LeoNerd" Evans
committed
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",
"insert_client_ip",
Paul "LeoNerd" Evans
committed
]),
Paul "LeoNerd" Evans
committed
resource_for_client=self.mock_resource,
resource_for_federation=self.mock_resource,
config=self.mock_config,
Paul "LeoNerd" Evans
committed
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
return {
"user": hs.parse_userid(myid),
"admin": False,
"device_id": None,
}
Paul "LeoNerd" Evans
committed
room_member_handler = hs.handlers.room_member_handler = Mock(
spec=[
"get_rooms_for_user",
]
)
Paul "LeoNerd" Evans
committed
hs.get_auth().get_user_by_token = _get_user_by_token
presence.register_servlets(hs, self.mock_resource)
self.u_apple = hs.parse_userid("@apple:test")
self.u_banana = hs.parse_userid("@banana:test")
@defer.inlineCallbacks
def test_get_my_list(self):
Paul "LeoNerd" Evans
committed
self.datastore.get_presence_list.return_value = defer.succeed(
[{"observed_user_id": "@banana:test"}],
Paul "LeoNerd" Evans
committed
(code, response) = yield self.mock_resource.trigger("GET",
Kegan Dougal
committed
"/presence/list/%s" % (myid), None)
Paul "LeoNerd" Evans
committed
self.assertEquals([
Paul "LeoNerd" Evans
committed
], response)
Paul "LeoNerd" Evans
committed
self.datastore.get_presence_list.assert_called_with(
"apple", accepted=True
)
@defer.inlineCallbacks
def test_invite(self):
Paul "LeoNerd" Evans
committed
self.datastore.add_presence_list_pending.return_value = (
defer.succeed(())
)
self.datastore.is_presence_visible.return_value = defer.succeed(
True
)
Paul "LeoNerd" Evans
committed
(code, response) = yield self.mock_resource.trigger("POST",
Kegan Dougal
committed
"/presence/list/%s" % (myid),
Paul "LeoNerd" Evans
committed
"""{"invite": ["@banana:test"]}"""
)
Paul "LeoNerd" Evans
committed
self.datastore.add_presence_list_pending.assert_called_with(
"apple", "@banana:test"
)
self.datastore.set_presence_list_accepted.assert_called_with(
"apple", "@banana:test"
)
@defer.inlineCallbacks
def test_drop(self):
Paul "LeoNerd" Evans
committed
self.datastore.del_presence_list.return_value = (
defer.succeed(())
)
Paul "LeoNerd" Evans
committed
(code, response) = yield self.mock_resource.trigger("POST",
Kegan Dougal
committed
"/presence/list/%s" % (myid),
Paul "LeoNerd" Evans
committed
"""{"drop": ["@banana:test"]}"""
)
Paul "LeoNerd" Evans
committed
self.datastore.del_presence_list.assert_called_with(
"apple", "@banana:test"
)
class PresenceEventStreamTestCase(unittest.TestCase):
def setUp(self):
Paul "LeoNerd" Evans
committed
self.mock_resource = MockHttpResource(prefix=PATH_PREFIX)
self.mock_config = Mock()
self.mock_config.signing_key = [MockKey()]
# HIDEOUS HACKERY
# TODO(paul): This should be injected in via the HomeServer DI system
Paul "LeoNerd" Evans
committed
from synapse.streams.events import (
Paul "LeoNerd" Evans
committed
PresenceEventSource, NullSource, EventSources
Paul "LeoNerd" Evans
committed
)
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()
}
Paul "LeoNerd" Evans
committed
EventSources.SOURCE_TYPES["presence"] = PresenceEventSource
hs = HomeServer("test",
db_pool=None,
http_client=None,
Paul "LeoNerd" Evans
committed
resource_for_client=self.mock_resource,
resource_for_federation=self.mock_resource,
datastore=Mock(spec=[
"set_presence_state",
"get_presence_list",
]),
clock=Mock(spec=[
"call_later",
"cancel_call_later",
"time_msec",
]),
)
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)
Paul "LeoNerd" Evans
committed
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
Paul "LeoNerd" Evans
committed
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
Paul "LeoNerd" Evans
committed
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
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):
Paul "LeoNerd" Evans
committed
self.room_members = [self.u_apple, self.u_banana]
self.mock_datastore.set_presence_state.return_value = defer.succeed(
self.mock_datastore.get_presence_list.return_value = defer.succeed(
Paul "LeoNerd" Evans
committed
(code, response) = yield self.mock_resource.trigger("GET",
"/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
Paul "LeoNerd" Evans
committed
self.assertEquals({"start": "0_1_0", "end": "0_1_0", "chunk": []},
response
)
self.mock_datastore.set_presence_state.return_value = defer.succeed(
self.mock_datastore.get_presence_list.return_value = defer.succeed(
yield self.presence.set_state(self.u_banana, self.u_banana,
Paul "LeoNerd" Evans
committed
state={"presence": ONLINE}
)
Paul "LeoNerd" Evans
committed
(code, response) = yield self.mock_resource.trigger("GET",
Paul "LeoNerd" Evans
committed
"/events?from=0_1_0&timeout=0", None)
Paul "LeoNerd" Evans
committed
self.assertEquals({"start": "0_1_0", "end": "0_2_0", "chunk": [
Paul "LeoNerd" Evans
committed
"content": {
"user_id": "@banana:test",
Paul "LeoNerd" Evans
committed
"presence": ONLINE,
Paul "LeoNerd" Evans
committed
"displayname": "Frank",
Paul "LeoNerd" Evans
committed
"last_active_ago": 0,
Paul "LeoNerd" Evans
committed
}},