From 8ada2d20183da9aac8182fbe80bdb897c5a4d224 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Tue, 9 Dec 2014 23:53:07 +0000 Subject: fix UTs by telling all the mock stores about the new methods for tracking retries --- tests/federation/test_federation.py | 5 +++++ tests/handlers/test_federation.py | 2 ++ tests/handlers/test_presence.py | 10 +++++++++- tests/handlers/test_typing.py | 9 +++++++-- 4 files changed, 23 insertions(+), 3 deletions(-) (limited to 'tests') diff --git a/tests/federation/test_federation.py b/tests/federation/test_federation.py index 73dd289276..f6b41e2c4c 100644 --- a/tests/federation/test_federation.py +++ b/tests/federation/test_federation.py @@ -25,6 +25,7 @@ from synapse.server import HomeServer from synapse.federation import initialize_http_replication from synapse.api.events import SynapseEvent +from synapse.storage.transactions import DestinationsTable def make_pdu(prev_pdus=[], **kwargs): """Provide some default fields for making a PduTuple.""" @@ -55,10 +56,14 @@ class FederationTestCase(unittest.TestCase): "delivered_txn", "get_received_txn_response", "set_received_txn_response", + "get_destination_retry_timings", ]) self.mock_persistence.get_received_txn_response.return_value = ( defer.succeed(None) ) + self.mock_persistence.get_destination_retry_timings.return_value = ( + defer.succeed(DestinationsTable.EntryType("", 0, 0)) + ) self.mock_config = Mock() self.mock_config.signing_key = [MockKey()] self.clock = MockClock() diff --git a/tests/handlers/test_federation.py b/tests/handlers/test_federation.py index 33016c16ef..fae33716a3 100644 --- a/tests/handlers/test_federation.py +++ b/tests/handlers/test_federation.py @@ -53,6 +53,8 @@ class FederationTestCase(unittest.TestCase): "persist_event", "store_room", "get_room", + "get_destination_retry_timings", + "set_destination_retry_timings", ]), resource_for_federation=NonCallableMock(), http_client=NonCallableMock(spec_set=[]), diff --git a/tests/handlers/test_presence.py b/tests/handlers/test_presence.py index fe69ce47eb..b85a89052a 100644 --- a/tests/handlers/test_presence.py +++ b/tests/handlers/test_presence.py @@ -30,7 +30,7 @@ from synapse.api.constants import PresenceState from synapse.api.errors import SynapseError from synapse.handlers.presence import PresenceHandler, UserPresenceCache from synapse.streams.config import SourcePaginationConfig - +from synapse.storage.transactions import DestinationsTable OFFLINE = PresenceState.OFFLINE UNAVAILABLE = PresenceState.UNAVAILABLE @@ -528,6 +528,7 @@ class PresencePushTestCase(unittest.TestCase): "delivered_txn", "get_received_txn_response", "set_received_txn_response", + "get_destination_retry_timings", ]), handlers=None, resource_for_client=Mock(), @@ -539,6 +540,9 @@ class PresencePushTestCase(unittest.TestCase): hs.handlers = JustPresenceHandlers(hs) self.datastore = hs.get_datastore() + self.datastore.get_destination_retry_timings.return_value = ( + defer.succeed(DestinationsTable.EntryType("", 0, 0)) + ) def get_received_txn_response(*args): return defer.succeed(None) @@ -1037,6 +1041,7 @@ class PresencePollingTestCase(unittest.TestCase): "delivered_txn", "get_received_txn_response", "set_received_txn_response", + "get_destination_retry_timings", ]), handlers=None, resource_for_client=Mock(), @@ -1048,6 +1053,9 @@ class PresencePollingTestCase(unittest.TestCase): hs.handlers = JustPresenceHandlers(hs) self.datastore = hs.get_datastore() + self.datastore.get_destination_retry_timings.return_value = ( + defer.succeed(DestinationsTable.EntryType("", 0, 0)) + ) def get_received_txn_response(*args): return defer.succeed(None) diff --git a/tests/handlers/test_typing.py b/tests/handlers/test_typing.py index adb5148351..2f170ac3bf 100644 --- a/tests/handlers/test_typing.py +++ b/tests/handlers/test_typing.py @@ -25,6 +25,8 @@ from ..utils import MockHttpResource, MockClock, DeferredMockCallable, MockKey from synapse.server import HomeServer from synapse.handlers.typing import TypingNotificationHandler +from synapse.storage.transactions import DestinationsTable + def _expect_edu(destination, edu_type, content, origin="test"): return { @@ -49,7 +51,6 @@ class JustTypingNotificationHandlers(object): def __init__(self, hs): self.typing_notification_handler = TypingNotificationHandler(hs) - class TypingNotificationsTestCase(unittest.TestCase): """Tests typing notifications to rooms.""" def setUp(self): @@ -72,6 +73,7 @@ class TypingNotificationsTestCase(unittest.TestCase): "delivered_txn", "get_received_txn_response", "set_received_txn_response", + "get_destination_retry_timings", ]), handlers=None, resource_for_client=Mock(), @@ -89,6 +91,9 @@ class TypingNotificationsTestCase(unittest.TestCase): self.handler.push_update_to_clients = self.mock_update_client self.datastore = hs.get_datastore() + self.datastore.get_destination_retry_timings.return_value = ( + defer.succeed(DestinationsTable.EntryType("", 0, 0)) + ) def get_received_txn_response(*args): return defer.succeed(None) @@ -162,7 +167,7 @@ class TypingNotificationsTestCase(unittest.TestCase): @defer.inlineCallbacks def test_started_typing_remote_send(self): self.room_members = [self.u_apple, self.u_onion] - + put_json = self.mock_http_client.put_json put_json.expect_call_and_return( call("farm", -- cgit 1.5.1 From f26ec14b2167a2a52e30f3e6d52f50cbb5cdbf52 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Wed, 10 Dec 2014 10:25:21 +0000 Subject: Remove whitespace --- tests/handlers/test_typing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/handlers/test_typing.py b/tests/handlers/test_typing.py index 2f170ac3bf..7b390e4346 100644 --- a/tests/handlers/test_typing.py +++ b/tests/handlers/test_typing.py @@ -167,7 +167,7 @@ class TypingNotificationsTestCase(unittest.TestCase): @defer.inlineCallbacks def test_started_typing_remote_send(self): self.room_members = [self.u_apple, self.u_onion] - + put_json = self.mock_http_client.put_json put_json.expect_call_and_return( call("farm", -- cgit 1.5.1 From 08aceea82e834119a0152198edef738d8350cba1 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Wed, 10 Dec 2014 10:26:12 +0000 Subject: Add newline back in --- tests/handlers/test_typing.py | 1 + 1 file changed, 1 insertion(+) (limited to 'tests') diff --git a/tests/handlers/test_typing.py b/tests/handlers/test_typing.py index 7b390e4346..7e6ed9a42f 100644 --- a/tests/handlers/test_typing.py +++ b/tests/handlers/test_typing.py @@ -51,6 +51,7 @@ class JustTypingNotificationHandlers(object): def __init__(self, hs): self.typing_notification_handler = TypingNotificationHandler(hs) + class TypingNotificationsTestCase(unittest.TestCase): """Tests typing notifications to rooms.""" def setUp(self): -- cgit 1.5.1 From 4d6af0dde3c8489928312060b7d2c69181a8dc41 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Wed, 10 Dec 2014 18:00:57 +0000 Subject: Fix some tests --- tests/handlers/test_typing.py | 2 +- tests/storage/test_redaction.py | 108 ++++++++++++++++++--------------------- tests/storage/test_roommember.py | 49 ++++++++++-------- tests/storage/test_stream.py | 73 ++++++++++++-------------- tests/test_types.py | 18 +++---- 5 files changed, 120 insertions(+), 130 deletions(-) (limited to 'tests') diff --git a/tests/handlers/test_typing.py b/tests/handlers/test_typing.py index 7e6ed9a42f..af466c474f 100644 --- a/tests/handlers/test_typing.py +++ b/tests/handlers/test_typing.py @@ -131,7 +131,7 @@ class TypingNotificationsTestCase(unittest.TestCase): if ignore_user is not None and member == ignore_user: continue - if member.is_mine: + if hs.is_mine(member): if localusers is not None: localusers.add(member) else: diff --git a/tests/storage/test_redaction.py b/tests/storage/test_redaction.py index adfe64a980..e8671ae3a2 100644 --- a/tests/storage/test_redaction.py +++ b/tests/storage/test_redaction.py @@ -23,7 +23,9 @@ from synapse.api.events.room import ( RoomMemberEvent, MessageEvent, RoomRedactionEvent, ) -from tests.utils import SQLiteMemoryDbPool +from tests.utils import SQLiteMemoryDbPool, MockKey + +from mock import Mock class RedactionTestCase(unittest.TestCase): @@ -33,13 +35,21 @@ class RedactionTestCase(unittest.TestCase): db_pool = SQLiteMemoryDbPool() yield db_pool.prepare() + self.mock_config = Mock() + self.mock_config.signing_key = [MockKey()] + hs = HomeServer( "test", db_pool=db_pool, + config=self.mock_config, + resource_for_federation=Mock(), + http_client=None, ) self.store = hs.get_datastore() - self.event_factory = hs.get_event_factory() + self.event_builder_factory = hs.get_event_builder_factory() + self.handlers = hs.get_handlers() + self.message_handler = self.handlers.message_handler self.u_alice = hs.parse_userid("@alice:test") self.u_bob = hs.parse_userid("@bob:test") @@ -49,35 +59,23 @@ class RedactionTestCase(unittest.TestCase): self.depth = 1 @defer.inlineCallbacks - def inject_room_member(self, room, user, membership, prev_state=None, + def inject_room_member(self, room, user, membership, replaces_state=None, extra_content={}): - self.depth += 1 - - event = self.event_factory.create_event( - etype=RoomMemberEvent.TYPE, - user_id=user.to_string(), - state_key=user.to_string(), - room_id=room.to_string(), - membership=membership, - content={"membership": membership}, - depth=self.depth, - prev_events=[], + content = {"membership": membership} + content.update(extra_content) + builder = self.event_builder_factory.new({ + "type": RoomMemberEvent.TYPE, + "sender": user.to_string(), + "state_key": user.to_string(), + "room_id": room.to_string(), + "content": content, + }) + + event, context = yield self.message_handler._create_new_client_event( + builder ) - event.content.update(extra_content) - - if prev_state: - event.prev_state = prev_state - - event.state_events = None - event.hashes = {} - event.prev_state = [] - event.auth_events = [] - - # Have to create a join event using the eventfactory - yield self.store.persist_event( - event - ) + yield self.store.persist_event(event, context) defer.returnValue(event) @@ -85,46 +83,38 @@ class RedactionTestCase(unittest.TestCase): def inject_message(self, room, user, body): self.depth += 1 - event = self.event_factory.create_event( - etype=MessageEvent.TYPE, - user_id=user.to_string(), - room_id=room.to_string(), - content={"body": body, "msgtype": u"message"}, - depth=self.depth, - prev_events=[], - ) - - event.state_events = None - event.hashes = {} - event.auth_events = [] + builder = self.event_builder_factory.new({ + "type": MessageEvent.TYPE, + "sender": user.to_string(), + "state_key": user.to_string(), + "room_id": room.to_string(), + "content": {"body": body, "msgtype": u"message"}, + }) - yield self.store.persist_event( - event + event, context = yield self.message_handler._create_new_client_event( + builder ) + yield self.store.persist_event(event, context) + defer.returnValue(event) @defer.inlineCallbacks def inject_redaction(self, room, event_id, user, reason): - event = self.event_factory.create_event( - etype=RoomRedactionEvent.TYPE, - user_id=user.to_string(), - room_id=room.to_string(), - content={"reason": reason}, - depth=self.depth, - redacts=event_id, - prev_events=[], + builder = self.event_builder_factory.new({ + "type": MessageEvent.TYPE, + "sender": user.to_string(), + "state_key": user.to_string(), + "room_id": room.to_string(), + "content": {"reason": reason}, + "redacts": event_id, + }) + + event, context = yield self.message_handler._create_new_client_event( + builder ) - event.state_events = None - event.hashes = {} - event.auth_events = [] - - yield self.store.persist_event( - event - ) - - defer.returnValue(event) + yield self.store.persist_event(event, context) @defer.inlineCallbacks def test_redact(self): diff --git a/tests/storage/test_roommember.py b/tests/storage/test_roommember.py index 8614e5ca9d..6df09952d1 100644 --- a/tests/storage/test_roommember.py +++ b/tests/storage/test_roommember.py @@ -21,7 +21,9 @@ from synapse.server import HomeServer from synapse.api.constants import Membership from synapse.api.events.room import RoomMemberEvent -from tests.utils import SQLiteMemoryDbPool +from tests.utils import SQLiteMemoryDbPool, MockKey + +from mock import Mock class RoomMemberStoreTestCase(unittest.TestCase): @@ -31,14 +33,22 @@ class RoomMemberStoreTestCase(unittest.TestCase): db_pool = SQLiteMemoryDbPool() yield db_pool.prepare() - hs = HomeServer("test", + self.mock_config = Mock() + self.mock_config.signing_key = [MockKey()] + + hs = HomeServer( + "test", db_pool=db_pool, + config=self.mock_config, + resource_for_federation=Mock(), + http_client=None, ) - # We can't test the RoomMemberStore on its own without the other event # storage logic self.store = hs.get_datastore() - self.event_factory = hs.get_event_factory() + self.event_builder_factory = hs.get_event_builder_factory() + self.handlers = hs.get_handlers() + self.message_handler = self.handlers.message_handler self.u_alice = hs.parse_userid("@alice:test") self.u_bob = hs.parse_userid("@bob:test") @@ -49,27 +59,22 @@ class RoomMemberStoreTestCase(unittest.TestCase): self.room = hs.parse_roomid("!abc123:test") @defer.inlineCallbacks - def inject_room_member(self, room, user, membership): - # Have to create a join event using the eventfactory - event = self.event_factory.create_event( - etype=RoomMemberEvent.TYPE, - user_id=user.to_string(), - state_key=user.to_string(), - room_id=room.to_string(), - membership=membership, - content={"membership": membership}, - depth=1, - prev_events=[], + def inject_room_member(self, room, user, membership, replaces_state=None): + builder = self.event_builder_factory.new({ + "type": RoomMemberEvent.TYPE, + "sender": user.to_string(), + "state_key": user.to_string(), + "room_id": room.to_string(), + "content": {"membership": membership}, + }) + + event, context = yield self.message_handler._create_new_client_event( + builder ) - event.state_events = None - event.hashes = {} - event.prev_state = {} - event.auth_events = {} + yield self.store.persist_event(event, context) - yield self.store.persist_event( - event - ) + defer.returnValue(event) @defer.inlineCallbacks def test_one_member(self): diff --git a/tests/storage/test_stream.py b/tests/storage/test_stream.py index 5038546aee..cba65bb9f0 100644 --- a/tests/storage/test_stream.py +++ b/tests/storage/test_stream.py @@ -21,7 +21,9 @@ from synapse.server import HomeServer from synapse.api.constants import Membership from synapse.api.events.room import RoomMemberEvent, MessageEvent -from tests.utils import SQLiteMemoryDbPool +from tests.utils import SQLiteMemoryDbPool, MockKey + +from mock import Mock class StreamStoreTestCase(unittest.TestCase): @@ -31,13 +33,21 @@ class StreamStoreTestCase(unittest.TestCase): db_pool = SQLiteMemoryDbPool() yield db_pool.prepare() + self.mock_config = Mock() + self.mock_config.signing_key = [MockKey()] + hs = HomeServer( "test", db_pool=db_pool, + config=self.mock_config, + resource_for_federation=Mock(), + http_client=None, ) self.store = hs.get_datastore() - self.event_factory = hs.get_event_factory() + self.event_builder_factory = hs.get_event_builder_factory() + self.handlers = hs.get_handlers() + self.message_handler = self.handlers.message_handler self.u_alice = hs.parse_userid("@alice:test") self.u_bob = hs.parse_userid("@bob:test") @@ -51,55 +61,40 @@ class StreamStoreTestCase(unittest.TestCase): def inject_room_member(self, room, user, membership, replaces_state=None): self.depth += 1 - event = self.event_factory.create_event( - etype=RoomMemberEvent.TYPE, - user_id=user.to_string(), - state_key=user.to_string(), - room_id=room.to_string(), - membership=membership, - content={"membership": membership}, - depth=self.depth, - prev_events=[], - ) - - event.state_events = None - event.hashes = {} - event.prev_state = [] - event.auth_events = [] - - if replaces_state: - event.prev_state = [(replaces_state, "hash")] - event.replaces_state = replaces_state + builder = self.event_builder_factory.new({ + "type": RoomMemberEvent.TYPE, + "sender": user.to_string(), + "state_key": user.to_string(), + "room_id": room.to_string(), + "content": {"membership": membership}, + }) - # Have to create a join event using the eventfactory - yield self.store.persist_event( - event + event, context = yield self.message_handler._create_new_client_event( + builder ) + yield self.store.persist_event(event, context) + defer.returnValue(event) @defer.inlineCallbacks def inject_message(self, room, user, body): self.depth += 1 - event = self.event_factory.create_event( - etype=MessageEvent.TYPE, - user_id=user.to_string(), - room_id=room.to_string(), - content={"body": body, "msgtype": u"message"}, - depth=self.depth, - prev_events=[], - ) - - event.state_events = None - event.hashes = {} - event.auth_events = [] + builder = self.event_builder_factory.new({ + "type": MessageEvent.TYPE, + "sender": user.to_string(), + "state_key": user.to_string(), + "room_id": room.to_string(), + "content": {"body": body, "msgtype": u"message"}, + }) - # Have to create a join event using the eventfactory - yield self.store.persist_event( - event + event, context = yield self.message_handler._create_new_client_event( + builder ) + yield self.store.persist_event(event, context) + @defer.inlineCallbacks def test_event_stream_get_other(self): # Both bob and alice joins the room diff --git a/tests/test_types.py b/tests/test_types.py index 276ecc91fd..bfb9e6f548 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -23,21 +23,21 @@ mock_homeserver = BaseHomeServer(hostname="my.domain") class UserIDTestCase(unittest.TestCase): def test_parse(self): - user = UserID.from_string("@1234abcd:my.domain", hs=mock_homeserver) + user = UserID.from_string("@1234abcd:my.domain") self.assertEquals("1234abcd", user.localpart) self.assertEquals("my.domain", user.domain) - self.assertEquals(True, user.is_mine) + self.assertEquals(True, mock_homeserver.is_mine(user)) def test_build(self): - user = UserID("5678efgh", "my.domain", True) + user = UserID("5678efgh", "my.domain") self.assertEquals(user.to_string(), "@5678efgh:my.domain") def test_compare(self): - userA = UserID.from_string("@userA:my.domain", hs=mock_homeserver) - userAagain = UserID.from_string("@userA:my.domain", hs=mock_homeserver) - userB = UserID.from_string("@userB:my.domain", hs=mock_homeserver) + userA = UserID.from_string("@userA:my.domain") + userAagain = UserID.from_string("@userA:my.domain") + userB = UserID.from_string("@userB:my.domain") self.assertTrue(userA == userAagain) self.assertTrue(userA != userB) @@ -52,14 +52,14 @@ class UserIDTestCase(unittest.TestCase): class RoomAliasTestCase(unittest.TestCase): def test_parse(self): - room = RoomAlias.from_string("#channel:my.domain", hs=mock_homeserver) + room = RoomAlias.from_string("#channel:my.domain") self.assertEquals("channel", room.localpart) self.assertEquals("my.domain", room.domain) - self.assertEquals(True, room.is_mine) + self.assertEquals(True, mock_homeserver.is_mine(room)) def test_build(self): - room = RoomAlias("channel", "my.domain", True) + room = RoomAlias("channel", "my.domain") self.assertEquals(room.to_string(), "#channel:my.domain") -- cgit 1.5.1 From be9a8d68e078a20967885df5cc25d38b3c1220d6 Mon Sep 17 00:00:00 2001 From: "Paul \"LeoNerd\" Evans" Date: Wed, 10 Dec 2014 19:13:50 +0000 Subject: Trivial test of MockClock() --- tests/test_test_utils.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 tests/test_test_utils.py (limited to 'tests') diff --git a/tests/test_test_utils.py b/tests/test_test_utils.py new file mode 100644 index 0000000000..11c5db3cd9 --- /dev/null +++ b/tests/test_test_utils.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# 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. + +from tests import unittest + +from tests.utils import MockClock + +class MockClockTestCase(unittest.TestCase): + + def setUp(self): + self.clock = MockClock() + + def test_advance_time(self): + start_time = self.clock.time() + + self.clock.advance_time(20) + + self.assertEquals(20, self.clock.time() - start_time) -- cgit 1.5.1 From 38da9884e70e8e44bde14c67a7a8a9d49a8b87ac Mon Sep 17 00:00:00 2001 From: "Paul \"LeoNerd\" Evans" Date: Wed, 10 Dec 2014 19:24:12 +0000 Subject: Implement .call_later() in MockClock --- tests/test_test_utils.py | 22 ++++++++++++++++++++++ tests/utils.py | 26 ++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) (limited to 'tests') diff --git a/tests/test_test_utils.py b/tests/test_test_utils.py index 11c5db3cd9..dcf946fc1a 100644 --- a/tests/test_test_utils.py +++ b/tests/test_test_utils.py @@ -28,3 +28,25 @@ class MockClockTestCase(unittest.TestCase): self.clock.advance_time(20) self.assertEquals(20, self.clock.time() - start_time) + + def test_later(self): + invoked = [0, 0] + + def _cb0(): + invoked[0] = 1 + self.clock.call_later(10, _cb0) + + def _cb1(): + invoked[1] = 1 + self.clock.call_later(20, _cb1) + + self.assertFalse(invoked[0]) + + self.clock.advance_time(15) + + self.assertTrue(invoked[0]) + self.assertFalse(invoked[1]) + + self.clock.advance_time(5) + + self.assertTrue(invoked[1]) diff --git a/tests/utils.py b/tests/utils.py index d8be73dba8..72843714fd 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -18,6 +18,8 @@ from synapse.api.errors import cs_error, CodeMessageException, StoreError from synapse.api.constants import Membership from synapse.storage import prepare_database +from synapse.util.logcontext import LoggingContext + from synapse.api.events.room import ( RoomMemberEvent, MessageEvent ) @@ -134,16 +136,40 @@ class MockKey(object): class MockClock(object): now = 1000 + def __init__(self): + # list of tuples of (absolute_time, callback) in no particular order + self.timers = [] + def time(self): return self.now def time_msec(self): return self.time() * 1000 + def call_later(self, delay, callback): + current_context = LoggingContext.current_context() + + def wrapped_callback(): + LoggingContext.thread_local.current_context = current_context + callback() + self.timers.append((self.now + delay, wrapped_callback)) + + def cancel_call_later(self, timer): + raise NotImplementedError("Oopsie") + # For unit testing def advance_time(self, secs): self.now += secs + timers = self.timers + self.timers = [] + + for time, callback in timers: + if self.now >= time: + callback() + else: + self.timers.append((time, callback)) + class SQLiteMemoryDbPool(ConnectionPool, object): def __init__(self): -- cgit 1.5.1 From 4551afc6d2f69ae3aa0ac37217fa0a94c0b2d62a Mon Sep 17 00:00:00 2001 From: "Paul \"LeoNerd\" Evans" Date: Wed, 10 Dec 2014 19:26:52 +0000 Subject: Implement .cancel_call_later() in MockClock --- tests/test_test_utils.py | 18 ++++++++++++++++++ tests/utils.py | 7 +++++-- 2 files changed, 23 insertions(+), 2 deletions(-) (limited to 'tests') diff --git a/tests/test_test_utils.py b/tests/test_test_utils.py index dcf946fc1a..b42787dd25 100644 --- a/tests/test_test_utils.py +++ b/tests/test_test_utils.py @@ -50,3 +50,21 @@ class MockClockTestCase(unittest.TestCase): self.clock.advance_time(5) self.assertTrue(invoked[1]) + + def test_cancel_later(self): + invoked = [0, 0] + + def _cb0(): + invoked[0] = 1 + t0 = self.clock.call_later(10, _cb0) + + def _cb1(): + invoked[1] = 1 + t1 = self.clock.call_later(20, _cb1) + + self.clock.cancel_call_later(t0) + + self.clock.advance_time(30) + + self.assertFalse(invoked[0]) + self.assertTrue(invoked[1]) diff --git a/tests/utils.py b/tests/utils.py index 72843714fd..f9a34748cd 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -152,10 +152,13 @@ class MockClock(object): def wrapped_callback(): LoggingContext.thread_local.current_context = current_context callback() - self.timers.append((self.now + delay, wrapped_callback)) + + t = (self.now + delay, wrapped_callback) + self.timers.append(t) + return t def cancel_call_later(self, timer): - raise NotImplementedError("Oopsie") + self.timers = [t for t in self.timers if t != timer] # For unit testing def advance_time(self, secs): -- cgit 1.5.1 From 9eb819e82801091362de7bd57c126ca5f60f1a8d Mon Sep 17 00:00:00 2001 From: "Paul \"LeoNerd\" Evans" Date: Wed, 10 Dec 2014 19:39:01 +0000 Subject: First hack at implementing timeouts in typing notification handler --- synapse/handlers/typing.py | 22 +++++++++++++++++++--- tests/handlers/test_typing.py | 36 +++++++++++++++++++++++++++++++++--- 2 files changed, 52 insertions(+), 6 deletions(-) (limited to 'tests') diff --git a/synapse/handlers/typing.py b/synapse/handlers/typing.py index d88a53242c..912cfd708b 100644 --- a/synapse/handlers/typing.py +++ b/synapse/handlers/typing.py @@ -43,7 +43,8 @@ class TypingNotificationHandler(BaseHandler): self.federation.register_edu_handler("m.typing", self._recv_edu) - self._member_typing_until = {} + self._member_typing_until = {} # clock time we expect to stop + self._member_typing_timer = {} # deferreds to manage theabove @defer.inlineCallbacks def started_typing(self, target_user, auth_user, room_id, timeout): @@ -58,7 +59,13 @@ class TypingNotificationHandler(BaseHandler): was_present = member in self._member_typing_until + if member in self._member_typing_timer: + self.clock.cancel_call_later(self._member_typing_timer[member]) + self._member_typing_until[member] = until + self._member_typing_timer[member] = self.clock.call_later( + timeout / 1000, lambda: self._stopped_typing(member) + ) if was_present: # No point sending another notification @@ -80,16 +87,25 @@ class TypingNotificationHandler(BaseHandler): member = RoomMember(room_id=room_id, user=target_user) + yield self._stopped_typing(member) + + @defer.inlineCallbacks + def _stopped_typing(self, member): if member not in self._member_typing_until: # No point defer.returnValue(None) yield self._push_update( - room_id=room_id, - user=target_user, + room_id=member.room_id, + user=member.user, typing=False, ) + del self._member_typing_until[member] + + self.clock.cancel_call_later(self._member_typing_timer[member]) + del self._member_typing_timer[member] + @defer.inlineCallbacks def _push_update(self, room_id, user, typing): localusers = set() diff --git a/tests/handlers/test_typing.py b/tests/handlers/test_typing.py index 7e6ed9a42f..6b9e22d396 100644 --- a/tests/handlers/test_typing.py +++ b/tests/handlers/test_typing.py @@ -238,9 +238,11 @@ class TypingNotificationsTestCase(unittest.TestCase): # Gut-wrenching from synapse.handlers.typing import RoomMember - self.handler._member_typing_until[ - RoomMember(self.room_id, self.u_apple) - ] = 1002000 + member = RoomMember(self.room_id, self.u_apple) + self.handler._member_typing_until[member] = 1002000 + self.handler._member_typing_timer[member] = ( + self.clock.call_later(1002, lambda: 0) + ) yield self.handler.stopped_typing( target_user=self.u_apple, @@ -256,3 +258,31 @@ class TypingNotificationsTestCase(unittest.TestCase): ]) yield put_json.await_calls() + + @defer.inlineCallbacks + def test_typing_timeout(self): + self.room_members = [self.u_apple, self.u_banana] + + yield self.handler.started_typing( + target_user=self.u_apple, + auth_user=self.u_apple, + room_id=self.room_id, + timeout=10000, + ) + + self.mock_update_client.assert_has_calls([ + call(observer_user=self.u_banana, + observed_user=self.u_apple, + room_id=self.room_id, + typing=True), + ]) + self.mock_update_client.reset_mock() + + self.clock.advance_time(11) + + self.mock_update_client.assert_has_calls([ + call(observer_user=self.u_banana, + observed_user=self.u_apple, + room_id=self.room_id, + typing=False), + ]) -- cgit 1.5.1 From 4006d58335a7dad88a30b74d0b50d2d6e80cc72d Mon Sep 17 00:00:00 2001 From: "Paul \"LeoNerd\" Evans" Date: Wed, 10 Dec 2014 20:48:12 +0000 Subject: Store serial numbers per room for typing event stream purposes --- synapse/handlers/typing.py | 41 ++++++++++++++++++++++++++------------ tests/handlers/test_typing.py | 46 +++++++++++++++---------------------------- 2 files changed, 44 insertions(+), 43 deletions(-) (limited to 'tests') diff --git a/synapse/handlers/typing.py b/synapse/handlers/typing.py index 912cfd708b..2370ff7134 100644 --- a/synapse/handlers/typing.py +++ b/synapse/handlers/typing.py @@ -46,6 +46,12 @@ class TypingNotificationHandler(BaseHandler): self._member_typing_until = {} # clock time we expect to stop self._member_typing_timer = {} # deferreds to manage theabove + # map room IDs to serial numbers + self._room_serials = {} + self._latest_room_serial = 0 + # map room IDs to sets of users currently typing + self._room_typing = {} + @defer.inlineCallbacks def started_typing(self, target_user, auth_user, room_id, timeout): if not target_user.is_mine: @@ -117,12 +123,11 @@ class TypingNotificationHandler(BaseHandler): ignore_user=user ) - for u in localusers: - self.push_update_to_clients( + if localusers: + self._push_update_local( room_id=room_id, - observer_user=u, - observed_user=user, - typing=typing, + user=user, + typing=typing ) deferreds = [] @@ -151,18 +156,28 @@ class TypingNotificationHandler(BaseHandler): room_id, localusers=localusers ) - for u in localusers: - self.push_update_to_clients( + if localusers: + self._push_update_local( room_id=room_id, - observer_user=u, - observed_user=user, + user=user, typing=content["typing"] ) - def push_update_to_clients(self, room_id, observer_user, observed_user, - typing): - # TODO(paul) steal this from presence.py - pass + def _push_update_local(self, room_id, user, typing): + if room_id not in self._room_serials: + self._room_serials[room_id] = 0 + self._room_typing[room_id] = set() + + room_set = self._room_typing[room_id] + if typing: + room_set.add(user) + elif user in room_set: + room_set.remove(user) + + self._latest_room_serial += 1 + self._room_serials[room_id] = self._latest_room_serial + + self.notifier.on_new_user_event(rooms=[room_id]) class TypingNotificationEventSource(object): diff --git a/tests/handlers/test_typing.py b/tests/handlers/test_typing.py index 6b9e22d396..898977ed8d 100644 --- a/tests/handlers/test_typing.py +++ b/tests/handlers/test_typing.py @@ -65,6 +65,9 @@ class TypingNotificationsTestCase(unittest.TestCase): self.mock_config = Mock() self.mock_config.signing_key = [MockKey()] + mock_notifier = Mock(spec=["on_new_user_event"]) + self.on_new_user_event = mock_notifier.on_new_user_event + hs = HomeServer("test", clock=self.clock, db_pool=None, @@ -77,6 +80,7 @@ class TypingNotificationsTestCase(unittest.TestCase): "get_destination_retry_timings", ]), handlers=None, + notifier=mock_notifier, resource_for_client=Mock(), resource_for_federation=self.mock_federation_resource, http_client=self.mock_http_client, @@ -85,11 +89,7 @@ class TypingNotificationsTestCase(unittest.TestCase): ) hs.handlers = JustTypingNotificationHandlers(hs) - self.mock_update_client = Mock() - self.mock_update_client.return_value = defer.succeed(None) - self.handler = hs.get_handlers().typing_notification_handler - self.handler.push_update_to_clients = self.mock_update_client self.datastore = hs.get_datastore() self.datastore.get_destination_retry_timings.return_value = ( @@ -158,11 +158,8 @@ class TypingNotificationsTestCase(unittest.TestCase): timeout=20000, ) - self.mock_update_client.assert_has_calls([ - call(observer_user=self.u_banana, - observed_user=self.u_apple, - room_id=self.room_id, - typing=True), + self.on_new_user_event.assert_has_calls([ + call(rooms=[self.room_id]), ]) @defer.inlineCallbacks @@ -209,11 +206,8 @@ class TypingNotificationsTestCase(unittest.TestCase): ) ) - self.mock_update_client.assert_has_calls([ - call(observer_user=self.u_apple, - observed_user=self.u_onion, - room_id=self.room_id, - typing=True), + self.on_new_user_event.assert_has_calls([ + call(rooms=[self.room_id]), ]) @defer.inlineCallbacks @@ -243,6 +237,7 @@ class TypingNotificationsTestCase(unittest.TestCase): self.handler._member_typing_timer[member] = ( self.clock.call_later(1002, lambda: 0) ) + self.handler._room_typing[self.room_id] = set((self.u_apple,)) yield self.handler.stopped_typing( target_user=self.u_apple, @@ -250,11 +245,8 @@ class TypingNotificationsTestCase(unittest.TestCase): room_id=self.room_id, ) - self.mock_update_client.assert_has_calls([ - call(observer_user=self.u_banana, - observed_user=self.u_apple, - room_id=self.room_id, - typing=False), + self.on_new_user_event.assert_has_calls([ + call(rooms=[self.room_id]), ]) yield put_json.await_calls() @@ -270,19 +262,13 @@ class TypingNotificationsTestCase(unittest.TestCase): timeout=10000, ) - self.mock_update_client.assert_has_calls([ - call(observer_user=self.u_banana, - observed_user=self.u_apple, - room_id=self.room_id, - typing=True), + self.on_new_user_event.assert_has_calls([ + call(rooms=[self.room_id]), ]) - self.mock_update_client.reset_mock() + self.on_new_user_event.reset_mock() self.clock.advance_time(11) - self.mock_update_client.assert_has_calls([ - call(observer_user=self.u_banana, - observed_user=self.u_apple, - room_id=self.room_id, - typing=False), + self.on_new_user_event.assert_has_calls([ + call(rooms=[self.room_id]), ]) -- cgit 1.5.1 From 1a75ff5c23e4d85714927f995e185ddf2d7eaff8 Mon Sep 17 00:00:00 2001 From: "Paul \"LeoNerd\" Evans" Date: Wed, 10 Dec 2014 21:01:49 +0000 Subject: Hook up the event stream to typing notifications --- synapse/handlers/typing.py | 24 +++++++++++++++-- tests/handlers/test_typing.py | 60 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 2 deletions(-) (limited to 'tests') diff --git a/synapse/handlers/typing.py b/synapse/handlers/typing.py index 2370ff7134..7426bda960 100644 --- a/synapse/handlers/typing.py +++ b/synapse/handlers/typing.py @@ -183,12 +183,32 @@ class TypingNotificationHandler(BaseHandler): class TypingNotificationEventSource(object): def __init__(self, hs): self.hs = hs + self.handler = hs.get_handlers().typing_notification_handler + + def _make_event_for(self, room_id): + typing = self.handler._room_typing[room_id] + return { + "type": "m.typing", + "room_id": room_id, + "typing": [u.to_string() for u in typing], + } def get_new_events_for_user(self, user, from_key, limit): - return ([], from_key) + from_key = int(from_key) + handler = self.handler + + events = [] + for room_id in handler._room_serials: + if handler._room_serials[room_id] <= from_key: + continue + + # TODO: check if user is in room + events.append(self._make_event_for(room_id)) + + return (events, handler._latest_room_serial) def get_current_key(self): - return 0 + return self.handler._latest_room_serial def get_pagination_rows(self, user, pagination_config, key): return ([], pagination_config.from_key) diff --git a/tests/handlers/test_typing.py b/tests/handlers/test_typing.py index 898977ed8d..b858f96323 100644 --- a/tests/handlers/test_typing.py +++ b/tests/handlers/test_typing.py @@ -91,6 +91,8 @@ class TypingNotificationsTestCase(unittest.TestCase): self.handler = hs.get_handlers().typing_notification_handler + self.event_source = hs.get_event_sources().sources["typing"] + self.datastore = hs.get_datastore() self.datastore.get_destination_retry_timings.return_value = ( defer.succeed(DestinationsTable.EntryType("", 0, 0)) @@ -151,6 +153,8 @@ class TypingNotificationsTestCase(unittest.TestCase): def test_started_typing_local(self): self.room_members = [self.u_apple, self.u_banana] + self.assertEquals(self.event_source.get_current_key(), 0) + yield self.handler.started_typing( target_user=self.u_apple, auth_user=self.u_apple, @@ -162,6 +166,16 @@ class TypingNotificationsTestCase(unittest.TestCase): call(rooms=[self.room_id]), ]) + self.assertEquals(self.event_source.get_current_key(), 1) + self.assertEquals( + self.event_source.get_new_events_for_user(self.u_apple, 0, None)[0], + [ + {"type": "m.typing", + "room_id": self.room_id, + "typing": [self.u_apple.to_string()]}, + ] + ) + @defer.inlineCallbacks def test_started_typing_remote_send(self): self.room_members = [self.u_apple, self.u_onion] @@ -195,6 +209,8 @@ class TypingNotificationsTestCase(unittest.TestCase): def test_started_typing_remote_recv(self): self.room_members = [self.u_apple, self.u_onion] + self.assertEquals(self.event_source.get_current_key(), 0) + yield self.mock_federation_resource.trigger("PUT", "/_matrix/federation/v1/send/1000000/", _make_edu_json("farm", "m.typing", @@ -210,6 +226,16 @@ class TypingNotificationsTestCase(unittest.TestCase): call(rooms=[self.room_id]), ]) + self.assertEquals(self.event_source.get_current_key(), 1) + self.assertEquals( + self.event_source.get_new_events_for_user(self.u_apple, 0, None)[0], + [ + {"type": "m.typing", + "room_id": self.room_id, + "typing": [self.u_onion.to_string()]}, + ] + ) + @defer.inlineCallbacks def test_stopped_typing(self): self.room_members = [self.u_apple, self.u_banana, self.u_onion] @@ -239,6 +265,8 @@ class TypingNotificationsTestCase(unittest.TestCase): ) self.handler._room_typing[self.room_id] = set((self.u_apple,)) + self.assertEquals(self.event_source.get_current_key(), 0) + yield self.handler.stopped_typing( target_user=self.u_apple, auth_user=self.u_apple, @@ -251,10 +279,22 @@ class TypingNotificationsTestCase(unittest.TestCase): yield put_json.await_calls() + self.assertEquals(self.event_source.get_current_key(), 1) + self.assertEquals( + self.event_source.get_new_events_for_user(self.u_apple, 0, None)[0], + [ + {"type": "m.typing", + "room_id": self.room_id, + "typing": []}, + ] + ) + @defer.inlineCallbacks def test_typing_timeout(self): self.room_members = [self.u_apple, self.u_banana] + self.assertEquals(self.event_source.get_current_key(), 0) + yield self.handler.started_typing( target_user=self.u_apple, auth_user=self.u_apple, @@ -267,8 +307,28 @@ class TypingNotificationsTestCase(unittest.TestCase): ]) self.on_new_user_event.reset_mock() + self.assertEquals(self.event_source.get_current_key(), 1) + self.assertEquals( + self.event_source.get_new_events_for_user(self.u_apple, 0, None)[0], + [ + {"type": "m.typing", + "room_id": self.room_id, + "typing": [self.u_apple.to_string()]}, + ] + ) + self.clock.advance_time(11) self.on_new_user_event.assert_has_calls([ call(rooms=[self.room_id]), ]) + + self.assertEquals(self.event_source.get_current_key(), 2) + self.assertEquals( + self.event_source.get_new_events_for_user(self.u_apple, 1, None)[0], + [ + {"type": "m.typing", + "room_id": self.room_id, + "typing": []}, + ] + ) -- cgit 1.5.1 From 8cdebce470869613658543cb79ed5dd97a5f0548 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Thu, 11 Dec 2014 13:25:19 +0000 Subject: Fix redactions. Fix 'age' key --- synapse/events/__init__.py | 1 + synapse/events/builder.py | 13 ++++++--- synapse/events/utils.py | 21 +++++++++++++++ synapse/state.py | 12 +++++++++ synapse/storage/_base.py | 60 ++++++++++++++++++++++++----------------- tests/storage/test_redaction.py | 6 ++--- 6 files changed, 83 insertions(+), 30 deletions(-) (limited to 'tests') diff --git a/synapse/events/__init__.py b/synapse/events/__init__.py index 7103b937af..98d7f0e324 100644 --- a/synapse/events/__init__.py +++ b/synapse/events/__init__.py @@ -97,6 +97,7 @@ class EventBase(object): origin_server_ts = _event_dict_property("origin_server_ts") prev_events = _event_dict_property("prev_events") prev_state = _event_dict_property("prev_state") + redacts = _event_dict_property("redacts") room_id = _event_dict_property("room_id") sender = _event_dict_property("sender") state_key = _event_dict_property("state_key") diff --git a/synapse/events/builder.py b/synapse/events/builder.py index 642264e9f3..9579b1fe8b 100644 --- a/synapse/events/builder.py +++ b/synapse/events/builder.py @@ -19,11 +19,18 @@ from synapse.types import EventID from synapse.util.stringutils import random_string +import copy + class EventBuilder(EventBase): def __init__(self, key_values={}): + signatures = copy.deepcopy(key_values.pop("signatures", {})) + unsigned = copy.deepcopy(key_values.pop("unsigned", {})) + super(EventBuilder, self).__init__( key_values, + signatures=signatures, + unsigned=unsigned ) def update_event_key(self, key, value): @@ -61,9 +68,9 @@ class EventBuilderFactory(object): key_values.setdefault("origin", self.hostname) key_values.setdefault("origin_server_ts", time_now) - if "unsigned" in key_values: - age = key_values["unsigned"].pop("age", 0) - key_values["unsigned"].setdefault("age_ts", time_now - age) + key_values.setdefault("unsigned", {}) + age = key_values["unsigned"].pop("age", 0) + key_values["unsigned"].setdefault("age_ts", time_now - age) key_values["signatures"] = {} diff --git a/synapse/events/utils.py b/synapse/events/utils.py index f5e135e3d0..6d9c9352e2 100644 --- a/synapse/events/utils.py +++ b/synapse/events/utils.py @@ -80,6 +80,11 @@ def prune_event(event): allowed_fields["content"] = new_content + allowed_fields["unsigned"] = {} + + if "age_ts" in event.unsigned: + allowed_fields["unsigned"]["age_ts"] = event.unsigned["age_ts"] + return type(event)(allowed_fields) @@ -97,4 +102,20 @@ def serialize_event(hs, e): d["user_id"] = d.pop("sender", None) + if "redacted_because" in e.unsigned: + d["redacted_because"] = serialize_event( + hs, e.unsigned["redacted_because"] + ) + + del d["unsigned"]["redacted_because"] + + if "redacted_by" in e.unsigned: + d["redacted_by"] = e.unsigned["redacted_by"] + del d["unsigned"]["redacted_by"] + + del d["auth_events"] + del d["prev_events"] + del d["hashes"] + del d["signatures"] + return d diff --git a/synapse/state.py b/synapse/state.py index 7fdf596006..5bfa73fb46 100644 --- a/synapse/state.py +++ b/synapse/state.py @@ -155,6 +155,12 @@ class StateHandler(object): else: context.auth_events = {} + if event.is_state(): + key = (event.type, event.state_key) + if key in context.current_state: + replaces = context.current_state[key] + event.unsigned["replaces_state"] = replaces.event_id + defer.returnValue([]) if event.is_state(): @@ -177,6 +183,12 @@ class StateHandler(object): prev_state ) + if event.is_state(): + key = (event.type, event.state_key) + if key in context.current_state: + replaces = context.current_state[key] + event.unsigned["replaces_state"] = replaces.event_id + if hasattr(event, "auth_events") and event.auth_events: auth_ids = zip(*event.auth_events)[0] context.auth_events = { diff --git a/synapse/storage/_base.py b/synapse/storage/_base.py index 12239fa074..ffc26d4a61 100644 --- a/synapse/storage/_base.py +++ b/synapse/storage/_base.py @@ -444,38 +444,50 @@ class SQLBaseStore(object): def _get_events_txn(self, txn, event_ids): events = [] for e_id in event_ids: - js = self._simple_select_one_onecol_txn( - txn, - table="event_json", - keyvalues={"event_id": e_id}, - retcol="json", - allow_none=True, - ) + ev = self._get_event_txn(txn, e_id) - if not js: - # FIXME (erikj): What should we actually do here? - continue + if ev: + events.append(ev) - d = json.loads(js) + return events - ev = FrozenEvent(d) + def _get_event_txn(self, txn, event_id, check_redacted=True): + sql = ( + "SELECT json, r.event_id FROM event_json as e " + "LEFT JOIN redactions as r ON e.event_id = r.redacts " + "WHERE e.event_id = ? " + "LIMIT 1 " + ) - if hasattr(ev, "redacted") and ev.redacted: - # Get the redaction event. - select_event_sql = "SELECT * FROM events WHERE event_id = ?" - txn.execute(select_event_sql, (ev.redacted,)) + txn.execute(sql, (event_id,)) - del_evs = self._parse_events_txn( - txn, self.cursor_to_dict(txn) - ) + res = txn.fetchone() - if del_evs: - ev = prune_event(ev) - ev.redacted_because = del_evs[0] + if not res: + return None - events.append(ev) + js, redacted = res - return events + d = json.loads(js) + + ev = FrozenEvent(d) + + if check_redacted and redacted: + ev = prune_event(ev) + + ev.unsigned["redacted_by"] = redacted + # Get the redaction event. + + because = self._get_event_txn( + txn, + redacted, + check_redacted=False + ) + + if because: + ev.unsigned["redacted_because"] = because + + return ev def _parse_events(self, rows): return self.runInteraction( diff --git a/tests/storage/test_redaction.py b/tests/storage/test_redaction.py index e8671ae3a2..d81f7add1c 100644 --- a/tests/storage/test_redaction.py +++ b/tests/storage/test_redaction.py @@ -149,7 +149,7 @@ class RedactionTestCase(unittest.TestCase): event, ) - self.assertFalse(hasattr(event, "redacted_because")) + self.assertFalse("redacted_because" in event.unsigned) # Redact event reason = "Because I said so" @@ -179,7 +179,7 @@ class RedactionTestCase(unittest.TestCase): event, ) - self.assertTrue(hasattr(event, "redacted_because")) + self.assertTrue("redacted_because" in event.unsigned) self.assertObjectHasAttributes( { @@ -187,7 +187,7 @@ class RedactionTestCase(unittest.TestCase): "user_id": self.u_alice.to_string(), "content": {"reason": reason}, }, - event.redacted_because, + event.unsigned["redacted_because"], ) @defer.inlineCallbacks -- cgit 1.5.1 From e72b16f9a37ca335fdc24224a3b8e403ff7d3085 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Thu, 11 Dec 2014 13:38:52 +0000 Subject: Fix redaction tests --- tests/storage/test_redaction.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'tests') diff --git a/tests/storage/test_redaction.py b/tests/storage/test_redaction.py index d81f7add1c..f670e154c3 100644 --- a/tests/storage/test_redaction.py +++ b/tests/storage/test_redaction.py @@ -102,7 +102,7 @@ class RedactionTestCase(unittest.TestCase): @defer.inlineCallbacks def inject_redaction(self, room, event_id, user, reason): builder = self.event_builder_factory.new({ - "type": MessageEvent.TYPE, + "type": RoomRedactionEvent.TYPE, "sender": user.to_string(), "state_key": user.to_string(), "room_id": room.to_string(), @@ -170,6 +170,10 @@ class RedactionTestCase(unittest.TestCase): event = results[0] + self.assertEqual(msg_event.event_id, event.event_id) + + self.assertTrue("redacted_because" in event.unsigned) + self.assertObjectHasAttributes( { "type": MessageEvent.TYPE, @@ -179,8 +183,6 @@ class RedactionTestCase(unittest.TestCase): event, ) - self.assertTrue("redacted_because" in event.unsigned) - self.assertObjectHasAttributes( { "type": RoomRedactionEvent.TYPE, @@ -247,6 +249,8 @@ class RedactionTestCase(unittest.TestCase): event = results[0] + self.assertTrue("redacted_because" in event.unsigned) + self.assertObjectHasAttributes( { "type": RoomMemberEvent.TYPE, @@ -256,13 +260,11 @@ class RedactionTestCase(unittest.TestCase): event, ) - self.assertTrue(hasattr(event, "redacted_because")) - self.assertObjectHasAttributes( { "type": RoomRedactionEvent.TYPE, "user_id": self.u_alice.to_string(), "content": {"reason": reason}, }, - event.redacted_because, + event.unsigned["redacted_because"], ) -- cgit 1.5.1 From 9191292b0f657f6210e88f16ffd9a182bfab8170 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Thu, 11 Dec 2014 15:16:55 +0000 Subject: Fix prev_content --- synapse/events/utils.py | 8 ++++++++ synapse/storage/_base.py | 6 ++++++ tests/storage/test_stream.py | 5 ++--- 3 files changed, 16 insertions(+), 3 deletions(-) (limited to 'tests') diff --git a/synapse/events/utils.py b/synapse/events/utils.py index 6d9c9352e2..4ab770dd5f 100644 --- a/synapse/events/utils.py +++ b/synapse/events/utils.py @@ -113,6 +113,14 @@ def serialize_event(hs, e): d["redacted_by"] = e.unsigned["redacted_by"] del d["unsigned"]["redacted_by"] + if "replaces_state" in e.unsigned: + d["replaces_state"] = e.unsigned["replaces_state"] + del d["unsigned"]["replaces_state"] + + if "prev_content" in e.unsigned: + d["prev_content"] = e.unsigned["prev_content"] + del d["unsigned"]["prev_content"] + del d["auth_events"] del d["prev_events"] del d["hashes"] diff --git a/synapse/storage/_base.py b/synapse/storage/_base.py index ffc26d4a61..e9cf73a8e2 100644 --- a/synapse/storage/_base.py +++ b/synapse/storage/_base.py @@ -487,6 +487,12 @@ class SQLBaseStore(object): if because: ev.unsigned["redacted_because"] = because + if "replaces_state" in ev.unsigned: + ev.unsigned["prev_content"] = self._get_event_txn( + txn, + ev.unsigned["replaces_state"], + ).get_dict()["content"] + return ev def _parse_events(self, rows): diff --git a/tests/storage/test_stream.py b/tests/storage/test_stream.py index cba65bb9f0..4865a5c142 100644 --- a/tests/storage/test_stream.py +++ b/tests/storage/test_stream.py @@ -58,7 +58,7 @@ class StreamStoreTestCase(unittest.TestCase): self.depth = 1 @defer.inlineCallbacks - def inject_room_member(self, room, user, membership, replaces_state=None): + def inject_room_member(self, room, user, membership): self.depth += 1 builder = self.event_builder_factory.new({ @@ -215,7 +215,6 @@ class StreamStoreTestCase(unittest.TestCase): event2 = yield self.inject_room_member( self.room1, self.u_alice, Membership.JOIN, - replaces_state=event1.event_id, ) end = yield self.store.get_room_events_max_id() @@ -233,6 +232,6 @@ class StreamStoreTestCase(unittest.TestCase): event = results[0] self.assertTrue( - hasattr(event, "prev_content"), + "prev_content" in event.unsigned, msg="No prev_content key" ) -- cgit 1.5.1 From 3b2cc260531c18681c29e771a79f3374013b5c63 Mon Sep 17 00:00:00 2001 From: "Paul \"LeoNerd\" Evans" Date: Thu, 11 Dec 2014 16:03:04 +0000 Subject: Initial hack at unit tests of room typing REST API --- synapse/handlers/typing.py | 7 +++++ tests/rest/test_rooms.py | 71 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 75 insertions(+), 3 deletions(-) (limited to 'tests') diff --git a/synapse/handlers/typing.py b/synapse/handlers/typing.py index 989f73947f..c2b890261a 100644 --- a/synapse/handlers/typing.py +++ b/synapse/handlers/typing.py @@ -52,6 +52,13 @@ class TypingNotificationHandler(BaseHandler): # map room IDs to sets of users currently typing self._room_typing = {} + def tearDown(self): + """Cancels all the pending timers. + Normally this shouldn't be needed, but it's required from unit tests + to avoid a "Reactor was unclean" warning.""" + for t in self._member_typing_timer.values(): + self.clock.cancel_call_later(t) + @defer.inlineCallbacks def started_typing(self, target_user, auth_user, room_id, timeout): if not target_user.is_mine: diff --git a/tests/rest/test_rooms.py b/tests/rest/test_rooms.py index ff7c9f0530..5273105304 100644 --- a/tests/rest/test_rooms.py +++ b/tests/rest/test_rooms.py @@ -1067,6 +1067,71 @@ class RoomInitialSyncTestCase(RestTestCase): self.assertTrue(self.user_id in presence_by_user) self.assertEquals("m.presence", presence_by_user[self.user_id]["type"]) -# (code, response) = yield self.mock_resource.trigger("GET", path, None) -# self.assertEquals(200, code, msg=str(response)) -# self.assert_dict(json.loads(content), response) + +class RoomTypingTestCase(RestTestCase): + """ Tests /rooms/$room_id/typing/$user_id REST API. """ + user_id = "@sid:red" + + @defer.inlineCallbacks + def setUp(self): + self.mock_resource = MockHttpResource(prefix=PATH_PREFIX) + self.auth_user_id = self.user_id + + self.mock_config = NonCallableMock() + self.mock_config.signing_key = [MockKey()] + + db_pool = SQLiteMemoryDbPool() + yield db_pool.prepare() + + hs = HomeServer( + "red", + db_pool=db_pool, + http_client=None, + replication_layer=Mock(), + ratelimiter=NonCallableMock(spec_set=[ + "send_message", + ]), + config=self.mock_config, + ) + self.hs = hs + + self.ratelimiter = hs.get_ratelimiter() + self.ratelimiter.send_message.return_value = (True, 0) + + hs.get_handlers().federation_handler = Mock() + + def _get_user_by_token(token=None): + return { + "user": hs.parse_userid(self.auth_user_id), + "admin": False, + "device_id": None, + } + + hs.get_auth().get_user_by_token = _get_user_by_token + + def _insert_client_ip(*args, **kwargs): + return defer.succeed(None) + hs.get_datastore().insert_client_ip = _insert_client_ip + + synapse.rest.room.register_servlets(hs, self.mock_resource) + + self.room_id = yield self.create_room_as(self.user_id) + + def tearDown(self): + self.hs.get_handlers().typing_notification_handler.tearDown() + + @defer.inlineCallbacks + def test_set_typing(self): + (code, _) = yield self.mock_resource.trigger("PUT", + "/rooms/%s/typing/%s" % (self.room_id, self.user_id), + '{"typing": true, "timeout": 30000}' + ) + self.assertEquals(200, code) + + @defer.inlineCallbacks + def test_set_not_typing(self): + (code, _) = yield self.mock_resource.trigger("PUT", + "/rooms/%s/typing/%s" % (self.room_id, self.user_id), + '{"typing": false}' + ) + self.assertEquals(200, code) -- cgit 1.5.1 From c161b6cf96992e6fa3af11fac770f1d6472103a4 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Thu, 11 Dec 2014 16:43:30 +0000 Subject: Fix room creation test --- tests/handlers/test_room.py | 68 ++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 34 deletions(-) (limited to 'tests') diff --git a/tests/handlers/test_room.py b/tests/handlers/test_room.py index 0279ab703a..1e6e7c3602 100644 --- a/tests/handlers/test_room.py +++ b/tests/handlers/test_room.py @@ -20,7 +20,7 @@ from tests import unittest from synapse.api.events.room import ( RoomMemberEvent, ) -from synapse.api.constants import Membership +from synapse.api.constants import EventTypes, Membership from synapse.handlers.room import RoomMemberHandler, RoomCreationHandler from synapse.handlers.profile import ProfileHandler from synapse.server import HomeServer @@ -254,13 +254,9 @@ class RoomCreationTest(unittest.TestCase): notifier=NonCallableMock(spec_set=["on_new_room_event"]), handlers=NonCallableMock(spec_set=[ "room_creation_handler", - "room_member_handler", - "federation_handler", + "message_handler", ]), auth=NonCallableMock(spec_set=["check", "add_auth_events"]), - state_handler=NonCallableMock(spec_set=[ - "annotate_event_with_state", - ]), ratelimiter=NonCallableMock(spec_set=[ "send_message", ]), @@ -271,30 +267,12 @@ class RoomCreationTest(unittest.TestCase): "handle_new_event", ]) - self.datastore = hs.get_datastore() self.handlers = hs.get_handlers() - self.notifier = hs.get_notifier() - self.state_handler = hs.get_state_handler() - self.hs = hs - - self.handlers.federation_handler = self.federation - self.handlers.room_creation_handler = RoomCreationHandler(self.hs) + self.handlers.room_creation_handler = RoomCreationHandler(hs) self.room_creation_handler = self.handlers.room_creation_handler - self.handlers.room_member_handler = NonCallableMock(spec_set=[ - "change_membership" - ]) - self.room_member_handler = self.handlers.room_member_handler - - def annotate(event): - event.state_events = {} - return defer.succeed(None) - self.state_handler.annotate_event_with_state.side_effect = annotate - - def hosts(room): - return defer.succeed([]) - self.datastore.get_joined_hosts_for_room.side_effect = hosts + self.message_handler = self.handlers.message_handler self.ratelimiter = hs.get_ratelimiter() self.ratelimiter.send_message.return_value = (True, 0) @@ -311,14 +289,36 @@ class RoomCreationTest(unittest.TestCase): config=config, ) - self.assertTrue(self.room_member_handler.change_membership.called) - join_event = self.room_member_handler.change_membership.call_args[0][0] + self.assertTrue(self.message_handler.handle_event.called) + + event_dicts = [ + e[0][0] for e in self.message_handler.handle_event.call_args_list + ] - self.assertEquals(RoomMemberEvent.TYPE, join_event.type) - self.assertEquals(room_id, join_event.room_id) - self.assertEquals(user_id, join_event.user_id) - self.assertEquals(user_id, join_event.state_key) + self.assertTrue(len(event_dicts) > 3) - self.assertTrue(self.state_handler.annotate_event_with_state.called) + self.assertDictContainsSubset( + { + "type": EventTypes.Create, + "sender": user_id, + "room_id": room_id, + }, + event_dicts[0] + ) + + self.assertEqual(user_id, event_dicts[0]["content"]["creator"]) - self.assertTrue(self.federation.handle_new_event.called) + 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"] + ) -- cgit 1.5.1 From d3eb12c7b8292f2879e5aa11cb5ffec05ce2a3a5 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Thu, 11 Dec 2014 17:01:27 +0000 Subject: Fix federation test --- synapse/handlers/federation.py | 2 +- tests/handlers/test_federation.py | 42 ++++++++++++++++++++++----------------- 2 files changed, 25 insertions(+), 19 deletions(-) (limited to 'tests') diff --git a/synapse/handlers/federation.py b/synapse/handlers/federation.py index 17779475b8..ddcb28c8e2 100644 --- a/synapse/handlers/federation.py +++ b/synapse/handlers/federation.py @@ -136,7 +136,7 @@ class FederationHandler(BaseHandler): if not check_event_content_hash(event): logger.warn( "Event content has been tampered, redacting %s, %s", - event.event_id, encode_canonical_json(event.get_full_dict()) + event.event_id, encode_canonical_json(event.get_dict()) ) event = redacted_event diff --git a/tests/handlers/test_federation.py b/tests/handlers/test_federation.py index fae33716a3..91f7351087 100644 --- a/tests/handlers/test_federation.py +++ b/tests/handlers/test_federation.py @@ -20,7 +20,7 @@ from synapse.api.events.room import ( MessageEvent, ) -from synapse.api.events import SynapseEvent +from synapse.events import FrozenEvent from synapse.handlers.federation import FederationHandler from synapse.server import HomeServer @@ -37,7 +37,7 @@ class FederationTestCase(unittest.TestCase): self.mock_config.signing_key = [MockKey()] self.state_handler = NonCallableMock(spec_set=[ - "annotate_event_with_state", + "annotate_context_with_state", ]) self.auth = NonCallableMock(spec_set=[ @@ -78,36 +78,42 @@ class FederationTestCase(unittest.TestCase): @defer.inlineCallbacks def test_msg(self): - pdu = SynapseEvent( - type=MessageEvent.TYPE, - room_id="foo", - content={"msgtype": u"fooo"}, - origin_server_ts=0, - event_id="$a:b", - user_id="@a:b", - origin="b", - auth_events=[], - hashes={"sha256":"AcLrgtUIqqwaGoHhrEvYG1YLDIsVPYJdSRGhkp3jJp8"}, - ) + pdu = FrozenEvent({ + "type": MessageEvent.TYPE, + "room_id": "foo", + "content": {"msgtype": u"fooo"}, + "origin_server_ts": 0, + "event_id": "$a:b", + "user_id":"@a:b", + "origin": "b", + "auth_events": [], + "hashes": {"sha256":"AcLrgtUIqqwaGoHhrEvYG1YLDIsVPYJdSRGhkp3jJp8"}, + }) self.datastore.persist_event.return_value = defer.succeed(None) self.datastore.get_room.return_value = defer.succeed(True) self.auth.check_host_in_room.return_value = defer.succeed(True) - def annotate(ev, old_state=None): - ev.old_state_events = [] + def annotate(ev, context, old_state=None): + context.current_state = {} + context.auth_events = {} return defer.succeed(False) - self.state_handler.annotate_event_with_state.side_effect = annotate + self.state_handler.annotate_context_with_state.side_effect = annotate yield self.handlers.federation_handler.on_receive_pdu( "fo", pdu, False ) self.datastore.persist_event.assert_called_once_with( - ANY, is_new_state=False, backfilled=False, current_state=None + ANY, + is_new_state=True, + backfilled=False, + current_state=None, + context=ANY, ) - self.state_handler.annotate_event_with_state.assert_called_once_with( + self.state_handler.annotate_context_with_state.assert_called_once_with( + ANY, ANY, old_state=None, ) -- cgit 1.5.1 From 3fecacd86b32ab8d5a2b16bc124167227eb8dcb7 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Thu, 11 Dec 2014 17:11:06 +0000 Subject: Fix replication tests --- tests/federation/test_federation.py | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'tests') diff --git a/tests/federation/test_federation.py b/tests/federation/test_federation.py index f6b41e2c4c..79ac1ce10d 100644 --- a/tests/federation/test_federation.py +++ b/tests/federation/test_federation.py @@ -23,25 +23,20 @@ from ..utils import MockHttpResource, MockClock, MockKey from synapse.server import HomeServer from synapse.federation import initialize_http_replication -from synapse.api.events import SynapseEvent +from synapse.events import FrozenEvent from synapse.storage.transactions import DestinationsTable + 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, + "prev_events": prev_pdus, } pdu_fields.update(kwargs) - return SynapseEvent(prev_pdus=prev_pdus, **pdu_fields) + return FrozenEvent(pdu_fields) class FederationTestCase(unittest.TestCase): @@ -176,7 +171,7 @@ class FederationTestCase(unittest.TestCase): (200, "OK") ) - pdu = SynapseEvent( + pdu = make_pdu( event_id="abc123def456", origin="red", user_id="@a:red", @@ -185,10 +180,9 @@ class FederationTestCase(unittest.TestCase): origin_server_ts=123456789001, depth=1, content={"text": "Here is the message"}, - destinations=["remote"], ) - yield self.federation.send_pdu(pdu) + yield self.federation.send_pdu(pdu, ["remote"]) self.mock_http_client.put_json.assert_called_with( "remote", -- cgit 1.5.1 From 1f26e56de003fcf0fe8a8f064611ca40e997a3e6 Mon Sep 17 00:00:00 2001 From: "Paul \"LeoNerd\" Evans" Date: Thu, 11 Dec 2014 17:31:56 +0000 Subject: Actually unit-test the event stream around REST typing tests --- tests/rest/test_rooms.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'tests') diff --git a/tests/rest/test_rooms.py b/tests/rest/test_rooms.py index 5273105304..a34f832758 100644 --- a/tests/rest/test_rooms.py +++ b/tests/rest/test_rooms.py @@ -1095,6 +1095,8 @@ class RoomTypingTestCase(RestTestCase): ) self.hs = hs + self.event_source = hs.get_event_sources().sources["typing"] + self.ratelimiter = hs.get_ratelimiter() self.ratelimiter.send_message.return_value = (True, 0) @@ -1116,6 +1118,8 @@ class RoomTypingTestCase(RestTestCase): synapse.rest.room.register_servlets(hs, self.mock_resource) self.room_id = yield self.create_room_as(self.user_id) + # Need another user to make notifications actually work + yield self.join(self.room_id, user="@jim:red") def tearDown(self): self.hs.get_handlers().typing_notification_handler.tearDown() @@ -1128,6 +1132,16 @@ class RoomTypingTestCase(RestTestCase): ) self.assertEquals(200, code) + self.assertEquals(self.event_source.get_current_key(), 1) + self.assertEquals( + self.event_source.get_new_events_for_user(self.user_id, 0, None)[0], + [ + {"type": "m.typing", + "room_id": self.room_id, + "typing": [self.user_id]}, + ] + ) + @defer.inlineCallbacks def test_set_not_typing(self): (code, _) = yield self.mock_resource.trigger("PUT", -- cgit 1.5.1 From 6e1531682b694f8db13244e08241f5f0476ea1fc Mon Sep 17 00:00:00 2001 From: "Paul \"LeoNerd\" Evans" Date: Thu, 11 Dec 2014 17:39:08 +0000 Subject: Move typing-notification REST tests into their own .py file --- tests/rest/test_rooms.py | 83 ---------------------------------- tests/rest/test_typing.py | 113 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+), 83 deletions(-) create mode 100644 tests/rest/test_typing.py (limited to 'tests') diff --git a/tests/rest/test_rooms.py b/tests/rest/test_rooms.py index a34f832758..1f719beb0a 100644 --- a/tests/rest/test_rooms.py +++ b/tests/rest/test_rooms.py @@ -1066,86 +1066,3 @@ class RoomInitialSyncTestCase(RestTestCase): } self.assertTrue(self.user_id in presence_by_user) self.assertEquals("m.presence", presence_by_user[self.user_id]["type"]) - - -class RoomTypingTestCase(RestTestCase): - """ Tests /rooms/$room_id/typing/$user_id REST API. """ - user_id = "@sid:red" - - @defer.inlineCallbacks - def setUp(self): - self.mock_resource = MockHttpResource(prefix=PATH_PREFIX) - self.auth_user_id = self.user_id - - self.mock_config = NonCallableMock() - self.mock_config.signing_key = [MockKey()] - - db_pool = SQLiteMemoryDbPool() - yield db_pool.prepare() - - hs = HomeServer( - "red", - db_pool=db_pool, - http_client=None, - replication_layer=Mock(), - ratelimiter=NonCallableMock(spec_set=[ - "send_message", - ]), - config=self.mock_config, - ) - self.hs = hs - - self.event_source = hs.get_event_sources().sources["typing"] - - self.ratelimiter = hs.get_ratelimiter() - self.ratelimiter.send_message.return_value = (True, 0) - - hs.get_handlers().federation_handler = Mock() - - def _get_user_by_token(token=None): - return { - "user": hs.parse_userid(self.auth_user_id), - "admin": False, - "device_id": None, - } - - hs.get_auth().get_user_by_token = _get_user_by_token - - def _insert_client_ip(*args, **kwargs): - return defer.succeed(None) - hs.get_datastore().insert_client_ip = _insert_client_ip - - synapse.rest.room.register_servlets(hs, self.mock_resource) - - self.room_id = yield self.create_room_as(self.user_id) - # Need another user to make notifications actually work - yield self.join(self.room_id, user="@jim:red") - - def tearDown(self): - self.hs.get_handlers().typing_notification_handler.tearDown() - - @defer.inlineCallbacks - def test_set_typing(self): - (code, _) = yield self.mock_resource.trigger("PUT", - "/rooms/%s/typing/%s" % (self.room_id, self.user_id), - '{"typing": true, "timeout": 30000}' - ) - self.assertEquals(200, code) - - self.assertEquals(self.event_source.get_current_key(), 1) - self.assertEquals( - self.event_source.get_new_events_for_user(self.user_id, 0, None)[0], - [ - {"type": "m.typing", - "room_id": self.room_id, - "typing": [self.user_id]}, - ] - ) - - @defer.inlineCallbacks - def test_set_not_typing(self): - (code, _) = yield self.mock_resource.trigger("PUT", - "/rooms/%s/typing/%s" % (self.room_id, self.user_id), - '{"typing": false}' - ) - self.assertEquals(200, code) diff --git a/tests/rest/test_typing.py b/tests/rest/test_typing.py new file mode 100644 index 0000000000..0b95d70718 --- /dev/null +++ b/tests/rest/test_typing.py @@ -0,0 +1,113 @@ +# -*- coding: utf-8 -*- +# 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. + +"""Tests REST events for /rooms paths.""" + +# twisted imports +from twisted.internet import defer + +import synapse.rest.room +from synapse.server import HomeServer + +from ..utils import MockHttpResource, SQLiteMemoryDbPool, MockKey +from .utils import RestTestCase + +from mock import Mock, NonCallableMock + + +PATH_PREFIX = "/_matrix/client/api/v1" + + +class RoomTypingTestCase(RestTestCase): + """ Tests /rooms/$room_id/typing/$user_id REST API. """ + user_id = "@sid:red" + + @defer.inlineCallbacks + def setUp(self): + self.mock_resource = MockHttpResource(prefix=PATH_PREFIX) + self.auth_user_id = self.user_id + + self.mock_config = NonCallableMock() + self.mock_config.signing_key = [MockKey()] + + db_pool = SQLiteMemoryDbPool() + yield db_pool.prepare() + + hs = HomeServer( + "red", + db_pool=db_pool, + http_client=None, + replication_layer=Mock(), + ratelimiter=NonCallableMock(spec_set=[ + "send_message", + ]), + config=self.mock_config, + ) + self.hs = hs + + self.event_source = hs.get_event_sources().sources["typing"] + + self.ratelimiter = hs.get_ratelimiter() + self.ratelimiter.send_message.return_value = (True, 0) + + hs.get_handlers().federation_handler = Mock() + + def _get_user_by_token(token=None): + return { + "user": hs.parse_userid(self.auth_user_id), + "admin": False, + "device_id": None, + } + + hs.get_auth().get_user_by_token = _get_user_by_token + + def _insert_client_ip(*args, **kwargs): + return defer.succeed(None) + hs.get_datastore().insert_client_ip = _insert_client_ip + + synapse.rest.room.register_servlets(hs, self.mock_resource) + + self.room_id = yield self.create_room_as(self.user_id) + # Need another user to make notifications actually work + yield self.join(self.room_id, user="@jim:red") + + def tearDown(self): + self.hs.get_handlers().typing_notification_handler.tearDown() + + @defer.inlineCallbacks + def test_set_typing(self): + (code, _) = yield self.mock_resource.trigger("PUT", + "/rooms/%s/typing/%s" % (self.room_id, self.user_id), + '{"typing": true, "timeout": 30000}' + ) + self.assertEquals(200, code) + + self.assertEquals(self.event_source.get_current_key(), 1) + self.assertEquals( + self.event_source.get_new_events_for_user(self.user_id, 0, None)[0], + [ + {"type": "m.typing", + "room_id": self.room_id, + "typing": [self.user_id]}, + ] + ) + + @defer.inlineCallbacks + def test_set_not_typing(self): + (code, _) = yield self.mock_resource.trigger("PUT", + "/rooms/%s/typing/%s" % (self.room_id, self.user_id), + '{"typing": false}' + ) + self.assertEquals(200, code) -- cgit 1.5.1 From 5ebc994f841508beb48f06d22073e08845c5f593 Mon Sep 17 00:00:00 2001 From: "Paul \"LeoNerd\" Evans" Date: Thu, 11 Dec 2014 18:11:43 +0000 Subject: Actually auth-check to ensure people can only send typing notifications for rooms they're actually in --- synapse/handlers/typing.py | 4 ++++ tests/handlers/test_typing.py | 10 ++++++++++ 2 files changed, 14 insertions(+) (limited to 'tests') diff --git a/synapse/handlers/typing.py b/synapse/handlers/typing.py index c55221c6df..fa903c251c 100644 --- a/synapse/handlers/typing.py +++ b/synapse/handlers/typing.py @@ -67,6 +67,8 @@ class TypingNotificationHandler(BaseHandler): if target_user != auth_user: raise AuthError(400, "Cannot set another user's typing state") + yield self.auth.check_joined_room(room_id, target_user.to_string()) + logger.debug( "%s has started typing in %s", target_user.to_string(), room_id ) @@ -102,6 +104,8 @@ class TypingNotificationHandler(BaseHandler): if target_user != auth_user: raise AuthError(400, "Cannot set another user's typing state") + yield self.auth.check_joined_room(room_id, target_user.to_string()) + logger.debug( "%s has stopped typing in %s", target_user.to_string(), room_id ) diff --git a/tests/handlers/test_typing.py b/tests/handlers/test_typing.py index b858f96323..bc19db8dfa 100644 --- a/tests/handlers/test_typing.py +++ b/tests/handlers/test_typing.py @@ -22,6 +22,7 @@ import json from ..utils import MockHttpResource, MockClock, DeferredMockCallable, MockKey +from synapse.api.errors import AuthError from synapse.server import HomeServer from synapse.handlers.typing import TypingNotificationHandler @@ -68,7 +69,10 @@ class TypingNotificationsTestCase(unittest.TestCase): mock_notifier = Mock(spec=["on_new_user_event"]) self.on_new_user_event = mock_notifier.on_new_user_event + self.auth = Mock(spec=[]) + hs = HomeServer("test", + auth=self.auth, clock=self.clock, db_pool=None, datastore=Mock(spec=[ @@ -142,6 +146,12 @@ class TypingNotificationsTestCase(unittest.TestCase): self.room_member_handler.fetch_room_distributions_into = ( fetch_room_distributions_into) + def check_joined_room(room_id, user_id): + if user_id not in [u.to_string() for u in self.room_members]: + raise AuthError(401, "User is not in the room") + + self.auth.check_joined_room = check_joined_room + # Some local users to test with self.u_apple = hs.parse_userid("@apple:test") self.u_banana = hs.parse_userid("@banana:test") -- cgit 1.5.1 From f25764943c81c145a8e787444c3b16c973e2286c Mon Sep 17 00:00:00 2001 From: "Paul \"LeoNerd\" Evans" Date: Thu, 11 Dec 2014 18:27:01 +0000 Subject: Add a 'user_left_room' distributor signal analogous to 'user_joined_room' --- synapse/handlers/room.py | 7 +++++++ tests/handlers/test_room.py | 44 +++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 48 insertions(+), 3 deletions(-) (limited to 'tests') diff --git a/synapse/handlers/room.py b/synapse/handlers/room.py index a000b44036..c802e8f69d 100644 --- a/synapse/handlers/room.py +++ b/synapse/handlers/room.py @@ -260,6 +260,7 @@ class RoomMemberHandler(BaseHandler): self.distributor = hs.get_distributor() self.distributor.declare("user_joined_room") + self.distributor.declare("user_left_room") @defer.inlineCallbacks def get_room_members(self, room_id, membership=Membership.JOIN): @@ -387,6 +388,12 @@ class RoomMemberHandler(BaseHandler): do_auth=do_auth, ) + if prev_state and prev_state.membership == Membership.JOIN: + user = self.hs.parse_userid(event.user_id) + self.distributor.fire( + "user_left_room", user=user, room_id=event.room_id + ) + defer.returnValue({"room_id": room_id}) @defer.inlineCallbacks diff --git a/tests/handlers/test_room.py b/tests/handlers/test_room.py index 0279ab703a..3a71ed0aed 100644 --- a/tests/handlers/test_room.py +++ b/tests/handlers/test_room.py @@ -222,14 +222,52 @@ class RoomMemberHandlerTestCase(unittest.TestCase): user=user, room_id=room_id ) - def _create_member(self, user_id, room_id): + @defer.inlineCallbacks + def test_simple_leave(self): + room_id = "!foo:red" + user_id = "@bob:red" + user = self.hs.parse_userid(user_id) + + event = self._create_member( + user_id=user_id, + room_id=room_id, + membership=Membership.LEAVE, + ) + + prev_state = NonCallableMock() + prev_state.membership = Membership.JOIN + prev_state.sender = user_id + self.datastore.get_room_member.return_value = defer.succeed(prev_state) + + event.state_events = { + (RoomMemberEvent.TYPE, user_id): event, + } + + event.old_state_events = { + (RoomMemberEvent.TYPE, user_id): self._create_member( + user_id=user_id, + room_id=room_id, + ), + } + + leave_signal_observer = Mock() + self.distributor.observe("user_left_room", leave_signal_observer) + + # Actual invocation + yield self.room_member_handler.change_membership(event) + + leave_signal_observer.assert_called_with( + user=user, room_id=room_id + ) + + def _create_member(self, user_id, room_id, membership=Membership.JOIN): return self.hs.get_event_factory().create_event( etype=RoomMemberEvent.TYPE, user_id=user_id, state_key=user_id, room_id=room_id, - membership=Membership.JOIN, - content={"membership": Membership.JOIN}, + membership=membership, + content={"membership": membership}, ) -- cgit 1.5.1 From fa4b610ae383bdced11068832d880d14b1df576d Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Fri, 12 Dec 2014 10:42:27 +0000 Subject: Fix stream test. Make sure we add join to auth_events for invitiations --- synapse/api/auth.py | 6 ++++++ tests/rest/test_events.py | 4 ---- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'tests') diff --git a/synapse/api/auth.py b/synapse/api/auth.py index cd0deeb0e6..c76f5180f6 100644 --- a/synapse/api/auth.py +++ b/synapse/api/auth.py @@ -61,6 +61,8 @@ class Auth(object): if event.type == RoomAliasesEvent.TYPE: return True + logger.debug("Auth events: %s", auth_events) + if event.type == RoomMemberEvent.TYPE: allowed = self.is_membership_change_allowed( event, auth_events @@ -389,8 +391,12 @@ class Auth(object): if join_rule_event: auth_ids.append(join_rule_event.event_id) + if e_type == Membership.JOIN: if member_event and not is_public: auth_ids.append(member_event.event_id) + else: + if member_event: + auth_ids.append(member_event.event_id) elif member_event: if member_event.content["membership"] == Membership.JOIN: auth_ids.append(member_event.event_id) diff --git a/tests/rest/test_events.py b/tests/rest/test_events.py index 4a3234c332..d3159e2cf4 100644 --- a/tests/rest/test_events.py +++ b/tests/rest/test_events.py @@ -113,9 +113,6 @@ class EventStreamPermissionsTestCase(RestTestCase): def setUp(self): self.mock_resource = MockHttpResource(prefix=PATH_PREFIX) - persistence_service = Mock(spec=["get_latest_pdus_in_context"]) - persistence_service.get_latest_pdus_in_context.return_value = [] - self.mock_config = NonCallableMock() self.mock_config.signing_key = [MockKey()] @@ -127,7 +124,6 @@ class EventStreamPermissionsTestCase(RestTestCase): db_pool=db_pool, http_client=None, replication_layer=Mock(), - persistence_service=persistence_service, clock=Mock(spec=[ "call_later", "cancel_call_later", -- cgit 1.5.1 From b0bb1756a9a85f476c6ebd03a7e78ad5f403311c Mon Sep 17 00:00:00 2001 From: "Paul \"LeoNerd\" Evans" Date: Fri, 12 Dec 2014 11:59:46 +0000 Subject: Send list of typing user IDs as 'user_ids' list within 'content', so that m.typing stream events have a toplevel content, for consistency with others --- synapse/handlers/typing.py | 4 +++- tests/handlers/test_typing.py | 20 +++++++++++++++----- tests/rest/test_typing.py | 4 +++- 3 files changed, 21 insertions(+), 7 deletions(-) (limited to 'tests') diff --git a/synapse/handlers/typing.py b/synapse/handlers/typing.py index 46a0b299a1..253fec514d 100644 --- a/synapse/handlers/typing.py +++ b/synapse/handlers/typing.py @@ -223,7 +223,9 @@ class TypingNotificationEventSource(object): return { "type": "m.typing", "room_id": room_id, - "typing": [u.to_string() for u in typing], + "content": { + "user_ids": [u.to_string() for u in typing], + }, } def get_new_events_for_user(self, user, from_key, limit): diff --git a/tests/handlers/test_typing.py b/tests/handlers/test_typing.py index bc19db8dfa..391e287adc 100644 --- a/tests/handlers/test_typing.py +++ b/tests/handlers/test_typing.py @@ -182,7 +182,9 @@ class TypingNotificationsTestCase(unittest.TestCase): [ {"type": "m.typing", "room_id": self.room_id, - "typing": [self.u_apple.to_string()]}, + "content": { + "user_ids": [self.u_apple.to_string()], + }}, ] ) @@ -242,7 +244,9 @@ class TypingNotificationsTestCase(unittest.TestCase): [ {"type": "m.typing", "room_id": self.room_id, - "typing": [self.u_onion.to_string()]}, + "content": { + "user_ids": [self.u_onion.to_string()], + }}, ] ) @@ -295,7 +299,9 @@ class TypingNotificationsTestCase(unittest.TestCase): [ {"type": "m.typing", "room_id": self.room_id, - "typing": []}, + "content": { + "user_ids": [], + }}, ] ) @@ -323,7 +329,9 @@ class TypingNotificationsTestCase(unittest.TestCase): [ {"type": "m.typing", "room_id": self.room_id, - "typing": [self.u_apple.to_string()]}, + "content": { + "user_ids": [self.u_apple.to_string()], + }}, ] ) @@ -339,6 +347,8 @@ class TypingNotificationsTestCase(unittest.TestCase): [ {"type": "m.typing", "room_id": self.room_id, - "typing": []}, + "content": { + "user_ids": [], + }}, ] ) diff --git a/tests/rest/test_typing.py b/tests/rest/test_typing.py index 0b95d70718..c550294d59 100644 --- a/tests/rest/test_typing.py +++ b/tests/rest/test_typing.py @@ -100,7 +100,9 @@ class RoomTypingTestCase(RestTestCase): [ {"type": "m.typing", "room_id": self.room_id, - "typing": [self.user_id]}, + "content": { + "user_ids": [self.user_id], + }}, ] ) -- cgit 1.5.1 From 41ff21c9074ae2859eb49dfba1bda21f4ec3ab6e Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Fri, 12 Dec 2014 14:10:32 +0000 Subject: Fix test. --- tests/rest/test_rooms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/rest/test_rooms.py b/tests/rest/test_rooms.py index ff7c9f0530..e2172366ef 100644 --- a/tests/rest/test_rooms.py +++ b/tests/rest/test_rooms.py @@ -503,7 +503,7 @@ class RoomsMemberListTestCase(RestTestCase): @defer.inlineCallbacks def test_get_member_list_mixed_memberships(self): - room_creator = "@some_other_guy:blue" + room_creator = "@some_other_guy:red" room_id = yield self.create_room_as(room_creator) room_path = "/rooms/%s/members" % room_id yield self.invite(room=room_id, src=room_creator, -- cgit 1.5.1 From ebf2ec3ce6ffe04d75d1d221fcf7d5bac268a1ab Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Fri, 12 Dec 2014 14:32:39 +0000 Subject: Fix membership handler test --- tests/handlers/test_room.py | 179 ++++++++++++++++++++++++-------------------- 1 file changed, 97 insertions(+), 82 deletions(-) (limited to 'tests') diff --git a/tests/handlers/test_room.py b/tests/handlers/test_room.py index 1e6e7c3602..15b2c265b6 100644 --- a/tests/handlers/test_room.py +++ b/tests/handlers/test_room.py @@ -47,7 +47,7 @@ class RoomMemberHandlerTestCase(unittest.TestCase): "get_room_member", "get_room", "store_room", - "snapshot_room", + "get_latest_events_in_room", ]), resource_for_federation=NonCallableMock(), http_client=NonCallableMock(spec_set=[]), @@ -63,7 +63,7 @@ class RoomMemberHandlerTestCase(unittest.TestCase): "check_host_in_room", ]), state_handler=NonCallableMock(spec_set=[ - "annotate_event_with_state", + "annotate_context_with_state", "get_current_state", ]), config=self.mock_config, @@ -91,9 +91,6 @@ class RoomMemberHandlerTestCase(unittest.TestCase): self.handlers.profile_handler = ProfileHandler(self.hs) self.room_member_handler = self.handlers.room_member_handler - self.snapshot = Mock() - self.datastore.snapshot_room.return_value = self.snapshot - self.ratelimiter = hs.get_ratelimiter() self.ratelimiter.send_message.return_value = (True, 0) @@ -104,50 +101,68 @@ class RoomMemberHandlerTestCase(unittest.TestCase): target_user_id = "@red:blue" content = {"membership": Membership.INVITE} - event = self.hs.get_event_factory().create_event( - etype=RoomMemberEvent.TYPE, - user_id=user_id, - state_key=target_user_id, - room_id=room_id, - membership=Membership.INVITE, - content=content, + 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([]) ) - self.auth.check_host_in_room.return_value = defer.succeed(True) + 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, + ), + } - store_id = "store_id_fooo" - self.datastore.persist_event.return_value = defer.succeed(store_id) + return defer.succeed(True) - self.datastore.get_room_member.return_value = defer.succeed(None) + self.state_handler.annotate_context_with_state.side_effect = annotate - event.old_state_events = { - (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, - ), - } + def add_auth(_, ctx): + ctx.auth_events = ctx.current_state[ + (RoomMemberEvent.TYPE, "@bob:red") + ] - event.state_events = event.old_state_events - event.state_events[(RoomMemberEvent.TYPE, target_user_id)] = event + return defer.succeed(True) + self.auth.add_auth_events.side_effect = add_auth - # Actual invocation - yield self.room_member_handler.change_membership(event) + def send_invite(domain, event): + return defer.succeed(event) - self.federation.handle_new_event.assert_called_once_with( - event, self.snapshot, + self.federation.send_invite.side_effect = send_invite + + room_handler = self.room_member_handler + event, context = yield room_handler._create_new_client_event( + builder ) - self.assertEquals( - set(["red", "green"]), - set(event.destinations) + 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 + event, context=context, ) self.notifier.on_new_room_event.assert_called_once_with( event, extra_users=[self.hs.parse_userid(target_user_id)] @@ -162,57 +177,56 @@ class RoomMemberHandlerTestCase(unittest.TestCase): user_id = "@bob:red" user = self.hs.parse_userid(user_id) - event = self._create_member( - user_id=user_id, - room_id=room_id, - ) + join_signal_observer = Mock() + self.distributor.observe("user_joined_room", join_signal_observer) - self.auth.check_host_in_room.return_value = defer.succeed(True) + 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}, + }) - store_id = "store_id_fooo" - self.datastore.persist_event.return_value = defer.succeed(store_id) - self.datastore.get_room.return_value = defer.succeed(1) # Not None. + self.datastore.get_latest_events_in_room.return_value = ( + defer.succeed([]) + ) - prev_state = NonCallableMock() - prev_state.membership = Membership.INVITE - prev_state.sender = "@foo:red" - self.datastore.get_room_member.return_value = defer.succeed(prev_state) + def annotate(_, ctx): + ctx.current_state = { + (RoomMemberEvent.TYPE, "@bob:red"): self._create_member( + user_id="@bob:red", + room_id=room_id, + membership=Membership.INVITE + ), + } - join_signal_observer = Mock() - self.distributor.observe("user_joined_room", join_signal_observer) + return defer.succeed(True) + + self.state_handler.annotate_context_with_state.side_effect = annotate - event.state_events = { - (RoomMemberEvent.TYPE, "@alice:green"): self._create_member( - user_id="@alice:green", - room_id=room_id, - ), - (RoomMemberEvent.TYPE, user_id): event, - } + def add_auth(_, ctx): + ctx.auth_events = ctx.current_state[ + (RoomMemberEvent.TYPE, "@bob:red") + ] - event.old_state_events = { - (RoomMemberEvent.TYPE, "@alice:green"): self._create_member( - user_id="@alice:green", - room_id=room_id, - ), - } + return defer.succeed(True) + self.auth.add_auth_events.side_effect = add_auth - event.state_events = event.old_state_events - event.state_events[(RoomMemberEvent.TYPE, user_id)] = event + room_handler = self.room_member_handler + event, context = yield room_handler._create_new_client_event( + builder + ) # Actual invocation - yield self.room_member_handler.change_membership(event) + yield room_handler.change_membership(event, context) self.federation.handle_new_event.assert_called_once_with( - event, self.snapshot - ) - - self.assertEquals( - set(["red", "green"]), - set(event.destinations) + event, None, destinations=set() ) self.datastore.persist_event.assert_called_once_with( - event + event, context=context ) self.notifier.on_new_room_event.assert_called_once_with( event, extra_users=[user] @@ -222,15 +236,16 @@ class RoomMemberHandlerTestCase(unittest.TestCase): user=user, room_id=room_id ) - def _create_member(self, user_id, room_id): - return self.hs.get_event_factory().create_event( - etype=RoomMemberEvent.TYPE, - user_id=user_id, - state_key=user_id, - room_id=room_id, - membership=Membership.JOIN, - content={"membership": Membership.JOIN}, - ) + 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() class RoomCreationTest(unittest.TestCase): -- cgit 1.5.1 From 1fc2a0e33ef6e88a79dbf4325468d8eb77db0f65 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Fri, 12 Dec 2014 15:08:29 +0000 Subject: Fix tests and remove debug logging --- synapse/http/server.py | 4 ---- tests/utils.py | 9 +++++++-- 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'tests') diff --git a/synapse/http/server.py b/synapse/http/server.py index 2d5d71c8aa..f33859cf76 100644 --- a/synapse/http/server.py +++ b/synapse/http/server.py @@ -124,14 +124,10 @@ class JsonResource(HttpServer, resource.Resource): # returned response. We pass both the request and any # matched groups from the regex to the callback. - logger.debug("url things: %r", m.groups()) - args = [ urllib.unquote(u).decode("UTF-8") for u in m.groups() ] - logger.debug("url things args: %r", args) - code, response = yield path_entry.callback( request, *args diff --git a/tests/utils.py b/tests/utils.py index f9a34748cd..70a221550c 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -29,7 +29,7 @@ from twisted.enterprise.adbapi import ConnectionPool from collections import namedtuple from mock import patch, Mock -import json +import urllib import urlparse from inspect import getcallargs @@ -103,9 +103,14 @@ class MockHttpResource(HttpServer): matcher = pattern.match(path) if matcher: try: + args = [ + urllib.unquote(u).decode("UTF-8") + for u in matcher.groups() + ] + (code, response) = yield func( mock_request, - *matcher.groups() + *args ) defer.returnValue((code, response)) except CodeMessageException as e: -- cgit 1.5.1 From 65cdf4e724f3c528aa38d578abd94334d55ce593 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Mon, 15 Dec 2014 15:03:27 +0000 Subject: Get current member state from current_state snapshot. Fix leave test. --- synapse/handlers/room.py | 6 +++--- tests/handlers/test_room.py | 13 ++++++++++++- 2 files changed, 15 insertions(+), 4 deletions(-) (limited to 'tests') diff --git a/synapse/handlers/room.py b/synapse/handlers/room.py index a1d542854d..d317f2b30e 100644 --- a/synapse/handlers/room.py +++ b/synapse/handlers/room.py @@ -343,9 +343,9 @@ class RoomMemberHandler(BaseHandler): """ target_user_id = event.state_key - # TODO(markjh): get prev state from snapshot. - prev_state = yield self.store.get_room_member( - target_user_id, event.room_id + prev_state = context.current_state.get( + (RoomMemberEvent.TYPE, target_user_id), + None ) room_id = event.room_id diff --git a/tests/handlers/test_room.py b/tests/handlers/test_room.py index 21853fdc50..9ae9335e29 100644 --- a/tests/handlers/test_room.py +++ b/tests/handlers/test_room.py @@ -270,7 +270,7 @@ class RoomMemberHandlerTestCase(unittest.TestCase): (RoomMemberEvent.TYPE, "@bob:red"): self._create_member( user_id="@bob:red", room_id=room_id, - membership=Membership.INVITE + membership=Membership.JOIN ), } @@ -297,6 +297,17 @@ class RoomMemberHandlerTestCase(unittest.TestCase): # Actual invocation yield room_handler.change_membership(event, context) + self.federation.handle_new_event.assert_called_once_with( + event, None, destinations=set(['red']) + ) + + self.datastore.persist_event.assert_called_once_with( + event, context=context + ) + self.notifier.on_new_room_event.assert_called_once_with( + event, extra_users=[user] + ) + leave_signal_observer.assert_called_with( user=user, room_id=room_id ) -- cgit 1.5.1 From cf6e5f1dbf3cecf693e45f293535e71ee31801ed Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Mon, 15 Dec 2014 17:01:12 +0000 Subject: Rename MessageHandler.handle_event. Add a few comments. --- synapse/handlers/_base.py | 5 +++++ synapse/handlers/directory.py | 2 +- synapse/handlers/message.py | 14 +++++++++++++- synapse/handlers/profile.py | 2 +- synapse/handlers/room.py | 8 ++++---- synapse/rest/room.py | 10 +++++----- tests/handlers/test_room.py | 5 +++-- 7 files changed, 32 insertions(+), 14 deletions(-) (limited to 'tests') diff --git a/synapse/handlers/_base.py b/synapse/handlers/_base.py index 14f75ecbc2..af8eb5f0f5 100644 --- a/synapse/handlers/_base.py +++ b/synapse/handlers/_base.py @@ -122,10 +122,15 @@ class BaseHandler(object): if event.content["membership"] == Membership.INVITE: invitee = self.hs.parse_userid(event.state_key) if not self.hs.is_mine(invitee): + # TODO: Can we add signature from remote server in a nicer + # way? If we have been invited by a remote server, we need + # to get them to sign the event. returned_invite = yield federation_handler.send_invite( invitee.domain, event, ) + + # TODO: Make sure the signatures actually are correct. event.signatures.update( returned_invite.signatures ) diff --git a/synapse/handlers/directory.py b/synapse/handlers/directory.py index 76fb897f20..4b0869cd9f 100644 --- a/synapse/handlers/directory.py +++ b/synapse/handlers/directory.py @@ -149,7 +149,7 @@ class DirectoryHandler(BaseHandler): aliases = yield self.store.get_aliases_for_room(room_id) msg_handler = self.hs.get_handlers().message_handler - yield msg_handler.handle_event({ + yield msg_handler.create_and_send_event({ "type": RoomAliasesEvent.TYPE, "state_key": self.hs.hostname, "room_id": room_id, diff --git a/synapse/handlers/message.py b/synapse/handlers/message.py index 4fa4ffea25..1eed38c6d1 100644 --- a/synapse/handlers/message.py +++ b/synapse/handlers/message.py @@ -138,7 +138,19 @@ class MessageHandler(BaseHandler): defer.returnValue(chunk) @defer.inlineCallbacks - def handle_event(self, event_dict): + def create_and_send_event(self, event_dict): + """ Given a dict from a client, create and handle a new event. + + Creates an FrozenEvent object, filling out auth_events, prev_events, + etc. + + Adds display names to Join membership events. + + Persists and notifies local clients and federation. + + Args: + event_dict (dict): An entire event + """ builder = self.event_builder_factory.new(event_dict) self.validator.validate_new(builder) diff --git a/synapse/handlers/profile.py b/synapse/handlers/profile.py index 18fd0914e2..33a2c167ec 100644 --- a/synapse/handlers/profile.py +++ b/synapse/handlers/profile.py @@ -209,7 +209,7 @@ class ProfileHandler(BaseHandler): ) msg_handler = self.hs.get_handlers().message_handler - yield msg_handler.handle_event({ + yield msg_handler.create_and_send_event({ "type": j.type, "room_id": j.room_id, "state_key": j.state_key, diff --git a/synapse/handlers/room.py b/synapse/handlers/room.py index d317f2b30e..f7cc869225 100644 --- a/synapse/handlers/room.py +++ b/synapse/handlers/room.py @@ -126,11 +126,11 @@ class RoomCreationHandler(BaseHandler): msg_handler = self.hs.get_handlers().message_handler for event in creation_events: - yield msg_handler.handle_event(event) + yield msg_handler.create_and_send_event(event) if "name" in config: name = config["name"] - yield msg_handler.handle_event({ + yield msg_handler.create_and_send_event({ "type": RoomNameEvent.TYPE, "room_id": room_id, "sender": user_id, @@ -139,7 +139,7 @@ class RoomCreationHandler(BaseHandler): if "topic" in config: topic = config["topic"] - yield msg_handler.handle_event({ + yield msg_handler.create_and_send_event({ "type": RoomTopicEvent.TYPE, "room_id": room_id, "sender": user_id, @@ -147,7 +147,7 @@ class RoomCreationHandler(BaseHandler): }) for invitee in invite_list: - yield msg_handler.handle_event({ + yield msg_handler.create_and_send_event({ "type": RoomMemberEvent.TYPE, "state_key": invitee, "room_id": room_id, diff --git a/synapse/rest/room.py b/synapse/rest/room.py index 25ee964555..1a527d27c1 100644 --- a/synapse/rest/room.py +++ b/synapse/rest/room.py @@ -157,7 +157,7 @@ class RoomStateEventRestServlet(RestServlet): event_dict["state_key"] = state_key msg_handler = self.handlers.message_handler - yield msg_handler.handle_event(event_dict) + yield msg_handler.create_and_send_event(event_dict) defer.returnValue((200, {})) @@ -176,7 +176,7 @@ class RoomSendEventRestServlet(RestServlet): content = _parse_json(request) msg_handler = self.handlers.message_handler - event = yield msg_handler.handle_event( + event = yield msg_handler.create_and_send_event( { "type": event_type, "content": content, @@ -237,7 +237,7 @@ class JoinRoomAliasServlet(RestServlet): defer.returnValue((200, ret_dict)) else: # room id msg_handler = self.handlers.message_handler - yield msg_handler.handle_event( + yield msg_handler.create_and_send_event( { "type": RoomMemberEvent.TYPE, "content": {"membership": Membership.JOIN}, @@ -401,7 +401,7 @@ class RoomMembershipRestServlet(RestServlet): membership_action = "leave" msg_handler = self.handlers.message_handler - yield msg_handler.handle_event( + yield msg_handler.create_and_send_event( { "type": RoomMemberEvent.TYPE, "content": {"membership": unicode(membership_action)}, @@ -439,7 +439,7 @@ class RoomRedactEventRestServlet(RestServlet): content = _parse_json(request) msg_handler = self.handlers.message_handler - event = yield msg_handler.handle_event( + event = yield msg_handler.create_and_send_event( { "type": RoomRedactionEvent.TYPE, "content": content, diff --git a/tests/handlers/test_room.py b/tests/handlers/test_room.py index 9ae9335e29..9c63f2a882 100644 --- a/tests/handlers/test_room.py +++ b/tests/handlers/test_room.py @@ -369,10 +369,11 @@ class RoomCreationTest(unittest.TestCase): config=config, ) - self.assertTrue(self.message_handler.handle_event.called) + self.assertTrue(self.message_handler.create_and_send_event.called) event_dicts = [ - e[0][0] for e in self.message_handler.handle_event.call_args_list + e[0][0] + for e in self.message_handler.create_and_send_event.call_args_list ] self.assertTrue(len(event_dicts) > 3) -- cgit 1.5.1 From 3c77d13aa5375274e267a0ea898ce6267fb67cdc Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Tue, 16 Dec 2014 11:29:05 +0000 Subject: Kill off synapse.api.events.* --- synapse/api/constants.py | 1 + synapse/api/events/__init__.py | 148 -------------------------- synapse/api/events/factory.py | 90 ---------------- synapse/api/events/room.py | 170 ----------------------------- synapse/api/events/utils.py | 85 --------------- synapse/api/events/validator.py | 87 --------------- synapse/federation/replication.py | 1 - synapse/handlers/directory.py | 4 +- synapse/handlers/federation.py | 22 ++-- synapse/handlers/message.py | 1 - synapse/handlers/room.py | 28 +++-- synapse/rest/__init__.py | 2 +- synapse/rest/base.py | 2 - synapse/rest/room.py | 9 +- synapse/server.py | 10 -- synapse/state.py | 4 +- synapse/storage/__init__.py | 16 ++- tests/events/__init__.py | 15 --- tests/events/test_events.py | 217 -------------------------------------- tests/handlers/test_federation.py | 7 +- tests/handlers/test_room.py | 25 ++--- tests/storage/test_redaction.py | 23 ++-- tests/storage/test_room.py | 8 +- tests/storage/test_roommember.py | 5 +- tests/storage/test_stream.py | 11 +- tests/utils.py | 8 +- 26 files changed, 74 insertions(+), 925 deletions(-) delete mode 100644 synapse/api/events/__init__.py delete mode 100644 synapse/api/events/factory.py delete mode 100644 synapse/api/events/room.py delete mode 100644 synapse/api/events/utils.py delete mode 100644 synapse/api/events/validator.py delete mode 100644 tests/events/__init__.py delete mode 100644 tests/events/test_events.py (limited to 'tests') diff --git a/synapse/api/constants.py b/synapse/api/constants.py index b668da4a26..4fc8b79a40 100644 --- a/synapse/api/constants.py +++ b/synapse/api/constants.py @@ -68,6 +68,7 @@ class EventTypes(object): PowerLevels = "m.room.power_levels" Aliases = "m.room.aliases" Redaction = "m.room.redaction" + Feedback = "m.room.message.feedback" # These are used for validation Message = "m.room.message" diff --git a/synapse/api/events/__init__.py b/synapse/api/events/__init__.py deleted file mode 100644 index 22939d011a..0000000000 --- a/synapse/api/events/__init__.py +++ /dev/null @@ -1,148 +0,0 @@ -# -*- coding: utf-8 -*- -# 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. - -from synapse.util.jsonobject import JsonEncodedObject - - -def serialize_event(hs, e): - # FIXME(erikj): To handle the case of presence events and the like - if not isinstance(e, SynapseEvent): - return e - - # Should this strip out None's? - d = {k: v for k, v in e.get_dict().items()} - if "age_ts" in d: - d["age"] = int(hs.get_clock().time_msec()) - d["age_ts"] - del d["age_ts"] - - return d - - -class SynapseEvent(JsonEncodedObject): - - """Base class for Synapse events. These are JSON objects which must abide - by a certain well-defined structure. - """ - - # Attributes that are currently assumed by the federation side: - # Mandatory: - # - event_id - # - room_id - # - type - # - is_state - # - # Optional: - # - state_key (mandatory when is_state is True) - # - prev_events (these can be filled out by the federation layer itself.) - # - prev_state - - valid_keys = [ - "event_id", - "type", - "room_id", - "user_id", # sender/initiator - "content", # HTTP body, JSON - "state_key", - "age_ts", - "prev_content", - "replaces_state", - "redacted_because", - "origin_server_ts", - ] - - internal_keys = [ - "is_state", - "depth", - "destinations", - "origin", - "outlier", - "redacted", - "prev_events", - "hashes", - "signatures", - "prev_state", - "auth_events", - "state_hash", - ] - - required_keys = [ - "event_id", - "room_id", - "content", - ] - - outlier = False - - def __init__(self, raises=True, **kwargs): - super(SynapseEvent, self).__init__(**kwargs) - # if "content" in kwargs: - # self.check_json(self.content, raises=raises) - - def get_content_template(self): - """ Retrieve the JSON template for this event as a dict. - - The template must be a dict representing the JSON to match. Only - required keys should be present. The values of the keys in the template - are checked via type() to the values of the same keys in the actual - event JSON. - - NB: If loading content via json.loads, you MUST define strings as - unicode. - - For example: - Content: - { - "name": u"bob", - "age": 18, - "friends": [u"mike", u"jill"] - } - Template: - { - "name": u"string", - "age": 0, - "friends": [u"string"] - } - The values "string" and 0 could be anything, so long as the types - are the same as the content. - """ - raise NotImplementedError("get_content_template not implemented.") - - def get_pdu_json(self, time_now=None): - pdu_json = self.get_full_dict() - pdu_json.pop("destinations", None) - pdu_json.pop("outlier", None) - pdu_json.pop("replaces_state", None) - pdu_json.pop("redacted", None) - pdu_json.pop("prev_content", None) - state_hash = pdu_json.pop("state_hash", None) - if state_hash is not None: - pdu_json.setdefault("unsigned", {})["state_hash"] = state_hash - content = pdu_json.get("content", {}) - content.pop("prev", None) - if time_now is not None and "age_ts" in pdu_json: - age = time_now - pdu_json["age_ts"] - pdu_json.setdefault("unsigned", {})["age"] = int(age) - del pdu_json["age_ts"] - user_id = pdu_json.pop("user_id") - pdu_json["sender"] = user_id - return pdu_json - - -class SynapseStateEvent(SynapseEvent): - - def __init__(self, **kwargs): - if "state_key" not in kwargs: - kwargs["state_key"] = "" - super(SynapseStateEvent, self).__init__(**kwargs) diff --git a/synapse/api/events/factory.py b/synapse/api/events/factory.py deleted file mode 100644 index 1b84e2b445..0000000000 --- a/synapse/api/events/factory.py +++ /dev/null @@ -1,90 +0,0 @@ -# -*- coding: utf-8 -*- -# 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. - -from synapse.api.events.room import ( - RoomTopicEvent, MessageEvent, RoomMemberEvent, FeedbackEvent, - InviteJoinEvent, RoomConfigEvent, RoomNameEvent, GenericEvent, - RoomPowerLevelsEvent, RoomJoinRulesEvent, - RoomCreateEvent, - RoomRedactionEvent, -) - -from synapse.types import EventID - -from synapse.util.stringutils import random_string - - -class EventFactory(object): - - _event_classes = [ - RoomTopicEvent, - RoomNameEvent, - MessageEvent, - RoomMemberEvent, - FeedbackEvent, - InviteJoinEvent, - RoomConfigEvent, - RoomPowerLevelsEvent, - RoomJoinRulesEvent, - RoomCreateEvent, - RoomRedactionEvent, - ] - - def __init__(self, hs): - self._event_list = {} # dict of TYPE to event class - for event_class in EventFactory._event_classes: - self._event_list[event_class.TYPE] = event_class - - self.clock = hs.get_clock() - self.hs = hs - - self.event_id_count = 0 - - def create_event_id(self): - i = str(self.event_id_count) - self.event_id_count += 1 - - local_part = str(int(self.clock.time())) + i + random_string(5) - - e_id = EventID.create(local_part, self.hs.hostname) - - return e_id.to_string() - - def create_event(self, etype=None, **kwargs): - kwargs["type"] = etype - if "event_id" not in kwargs: - kwargs["event_id"] = self.create_event_id() - kwargs["origin"] = self.hs.hostname - else: - ev_id = self.hs.parse_eventid(kwargs["event_id"]) - kwargs["origin"] = ev_id.domain - - if "origin_server_ts" not in kwargs: - kwargs["origin_server_ts"] = int(self.clock.time_msec()) - - # The "age" key is a delta timestamp that should be converted into an - # absolute timestamp the minute we see it. - if "age" in kwargs: - kwargs["age_ts"] = int(self.clock.time_msec()) - int(kwargs["age"]) - del kwargs["age"] - elif "age_ts" not in kwargs: - kwargs["age_ts"] = int(self.clock.time_msec()) - - if etype in self._event_list: - handler = self._event_list[etype] - else: - handler = GenericEvent - - return handler(**kwargs) diff --git a/synapse/api/events/room.py b/synapse/api/events/room.py deleted file mode 100644 index 8c4ac45d02..0000000000 --- a/synapse/api/events/room.py +++ /dev/null @@ -1,170 +0,0 @@ -# -*- coding: utf-8 -*- -# 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. - -from synapse.api.constants import Feedback, Membership -from synapse.api.errors import SynapseError -from . import SynapseEvent, SynapseStateEvent - - -class GenericEvent(SynapseEvent): - def get_content_template(self): - return {} - - -class RoomTopicEvent(SynapseEvent): - TYPE = "m.room.topic" - - internal_keys = SynapseEvent.internal_keys + [ - "topic", - ] - - def __init__(self, **kwargs): - kwargs["state_key"] = "" - if "topic" in kwargs["content"]: - kwargs["topic"] = kwargs["content"]["topic"] - super(RoomTopicEvent, self).__init__(**kwargs) - - def get_content_template(self): - return {"topic": u"string"} - - -class RoomNameEvent(SynapseEvent): - TYPE = "m.room.name" - - internal_keys = SynapseEvent.internal_keys + [ - "name", - ] - - def __init__(self, **kwargs): - kwargs["state_key"] = "" - if "name" in kwargs["content"]: - kwargs["name"] = kwargs["content"]["name"] - super(RoomNameEvent, self).__init__(**kwargs) - - def get_content_template(self): - return {"name": u"string"} - - -class RoomMemberEvent(SynapseEvent): - TYPE = "m.room.member" - - valid_keys = SynapseEvent.valid_keys + [ - # target is the state_key - "membership", # action - ] - - def __init__(self, **kwargs): - if "membership" not in kwargs: - kwargs["membership"] = kwargs.get("content", {}).get("membership") - if not kwargs["membership"] in Membership.LIST: - raise SynapseError(400, "Bad membership value.") - super(RoomMemberEvent, self).__init__(**kwargs) - - def get_content_template(self): - return {"membership": u"string"} - - -class MessageEvent(SynapseEvent): - TYPE = "m.room.message" - - valid_keys = SynapseEvent.valid_keys + [ - "msg_id", # unique per room + user combo - ] - - def __init__(self, **kwargs): - super(MessageEvent, self).__init__(**kwargs) - - def get_content_template(self): - return {"msgtype": u"string"} - - -class FeedbackEvent(SynapseEvent): - TYPE = "m.room.message.feedback" - - valid_keys = SynapseEvent.valid_keys - - def __init__(self, **kwargs): - super(FeedbackEvent, self).__init__(**kwargs) - if not kwargs["content"]["type"] in Feedback.LIST: - raise SynapseError(400, "Bad feedback value.") - - def get_content_template(self): - return { - "type": u"string", - "target_event_id": u"string" - } - - -class InviteJoinEvent(SynapseEvent): - TYPE = "m.room.invite_join" - - valid_keys = SynapseEvent.valid_keys + [ - # target_user_id is the state_key - "target_host", - ] - - def __init__(self, **kwargs): - super(InviteJoinEvent, self).__init__(**kwargs) - - def get_content_template(self): - return {} - - -class RoomConfigEvent(SynapseEvent): - TYPE = "m.room.config" - - def __init__(self, **kwargs): - kwargs["state_key"] = "" - super(RoomConfigEvent, self).__init__(**kwargs) - - def get_content_template(self): - return {} - - -class RoomCreateEvent(SynapseStateEvent): - TYPE = "m.room.create" - - def get_content_template(self): - return {} - - -class RoomJoinRulesEvent(SynapseStateEvent): - TYPE = "m.room.join_rules" - - def get_content_template(self): - return {} - - -class RoomPowerLevelsEvent(SynapseStateEvent): - TYPE = "m.room.power_levels" - - def get_content_template(self): - return {} - - -class RoomAliasesEvent(SynapseStateEvent): - TYPE = "m.room.aliases" - - def get_content_template(self): - return {} - - -class RoomRedactionEvent(SynapseEvent): - TYPE = "m.room.redaction" - - valid_keys = SynapseEvent.valid_keys + ["redacts"] - - def get_content_template(self): - return {} diff --git a/synapse/api/events/utils.py b/synapse/api/events/utils.py deleted file mode 100644 index d6019d56eb..0000000000 --- a/synapse/api/events/utils.py +++ /dev/null @@ -1,85 +0,0 @@ -# -*- coding: utf-8 -*- -# 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. - -from .room import ( - RoomMemberEvent, RoomJoinRulesEvent, RoomPowerLevelsEvent, - RoomAliasesEvent, RoomCreateEvent, -) - - -def prune_event(event): - """ Returns a pruned version of the given event, which removes all keys we - don't know about or think could potentially be dodgy. - - This is used when we "redact" an event. We want to remove all fields that - the user has specified, but we do want to keep necessary information like - type, state_key etc. - """ - event_type = event.type - - allowed_keys = [ - "event_id", - "user_id", - "room_id", - "hashes", - "signatures", - "content", - "type", - "state_key", - "depth", - "prev_events", - "prev_state", - "auth_events", - "origin", - "origin_server_ts", - ] - - new_content = {} - - def add_fields(*fields): - for field in fields: - if field in event.content: - new_content[field] = event.content[field] - - if event_type == RoomMemberEvent.TYPE: - add_fields("membership") - elif event_type == RoomCreateEvent.TYPE: - add_fields("creator") - elif event_type == RoomJoinRulesEvent.TYPE: - add_fields("join_rule") - elif event_type == RoomPowerLevelsEvent.TYPE: - add_fields( - "users", - "users_default", - "events", - "events_default", - "events_default", - "state_default", - "ban", - "kick", - "redact", - ) - elif event_type == RoomAliasesEvent.TYPE: - add_fields("aliases") - - allowed_fields = { - k: v - for k, v in event.get_full_dict().items() - if k in allowed_keys - } - - allowed_fields["content"] = new_content - - return type(event)(**allowed_fields) diff --git a/synapse/api/events/validator.py b/synapse/api/events/validator.py deleted file mode 100644 index 067215f6ef..0000000000 --- a/synapse/api/events/validator.py +++ /dev/null @@ -1,87 +0,0 @@ -# -*- coding: utf-8 -*- -# 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. - -from synapse.api.errors import SynapseError, Codes - - -class EventValidator(object): - def __init__(self, hs): - pass - - def validate(self, event): - """Checks the given JSON content abides by the rules of the template. - - Args: - content : A JSON object to check. - raises: True to raise a SynapseError if the check fails. - Returns: - True if the content passes the template. Returns False if the check - fails and raises=False. - Raises: - SynapseError if the check fails and raises=True. - """ - # recursively call to inspect each layer - err_msg = self._check_json_template( - event.content, - event.get_content_template() - ) - if err_msg: - raise SynapseError(400, err_msg, Codes.BAD_JSON) - else: - return True - - def _check_json_template(self, content, template): - """Check content and template matches. - - If the template is a dict, each key in the dict will be validated with - the content, else it will just compare the types of content and - template. This basic type check is required because this function will - be recursively called and could be called with just strs or ints. - - Args: - content: The content to validate. - template: The validation template. - Returns: - str: An error message if the validation fails, else None. - """ - if type(content) != type(template): - return "Mismatched types: %s" % template - - if type(template) == dict: - for key in template: - if key not in content: - return "Missing %s key" % key - - if type(content[key]) != type(template[key]): - return "Key %s is of the wrong type (got %s, want %s)" % ( - key, type(content[key]), type(template[key])) - - if type(content[key]) == dict: - # we must go deeper - msg = self._check_json_template( - content[key], - template[key] - ) - if msg: - return msg - elif type(content[key]) == list: - # make sure each item type in content matches the template - for entry in content[key]: - msg = self._check_json_template( - entry, - template[key][0] - ) - if msg: - return msg diff --git a/synapse/federation/replication.py b/synapse/federation/replication.py index 6388bb98e2..9f8aadccca 100644 --- a/synapse/federation/replication.py +++ b/synapse/federation/replication.py @@ -74,7 +74,6 @@ class ReplicationLayer(object): self._clock = hs.get_clock() - self.event_factory = hs.get_event_factory() self.event_builder_factory = hs.get_event_builder_factory() def set_handler(self, handler): diff --git a/synapse/handlers/directory.py b/synapse/handlers/directory.py index 4b0869cd9f..404baea796 100644 --- a/synapse/handlers/directory.py +++ b/synapse/handlers/directory.py @@ -18,7 +18,7 @@ from twisted.internet import defer from ._base import BaseHandler from synapse.api.errors import SynapseError, Codes, CodeMessageException -from synapse.api.events.room import RoomAliasesEvent +from synapse.api.constants import EventTypes import logging @@ -150,7 +150,7 @@ class DirectoryHandler(BaseHandler): msg_handler = self.hs.get_handlers().message_handler yield msg_handler.create_and_send_event({ - "type": RoomAliasesEvent.TYPE, + "type": EventTypes.Aliases, "state_key": self.hs.hostname, "room_id": room_id, "sender": user_id, diff --git a/synapse/handlers/federation.py b/synapse/handlers/federation.py index c00f5a7031..16a104c0e2 100644 --- a/synapse/handlers/federation.py +++ b/synapse/handlers/federation.py @@ -22,8 +22,7 @@ from synapse.events.utils import prune_event from synapse.api.errors import ( AuthError, FederationError, SynapseError, StoreError, ) -from synapse.api.events.room import RoomMemberEvent, RoomCreateEvent -from synapse.api.constants import Membership +from synapse.api.constants import EventTypes, Membership from synapse.util.logutils import log_function from synapse.util.async import run_on_reactor from synapse.crypto.event_signing import ( @@ -225,7 +224,7 @@ class FederationHandler(BaseHandler): if not backfilled: extra_users = [] - if event.type == RoomMemberEvent.TYPE: + if event.type == EventTypes.Member: target_user_id = event.state_key target_user = self.hs.parse_userid(target_user_id) extra_users.append(target_user) @@ -234,7 +233,7 @@ class FederationHandler(BaseHandler): event, extra_users=extra_users ) - if event.type == RoomMemberEvent.TYPE: + if event.type == EventTypes.Member: if event.membership == Membership.JOIN: user = self.hs.parse_userid(event.state_key) yield self.distributor.fire( @@ -333,7 +332,8 @@ class FederationHandler(BaseHandler): event = pdu # We should assert some things. - assert(event.type == RoomMemberEvent.TYPE) + # FIXME: Do this in a nicer way + assert(event.type == EventTypes.Member) assert(event.user_id == joinee) assert(event.state_key == joinee) assert(event.room_id == room_id) @@ -450,7 +450,7 @@ class FederationHandler(BaseHandler): process it until the other server has signed it and sent it back. """ builder = self.event_builder_factory.new({ - "type": RoomMemberEvent.TYPE, + "type": EventTypes.Member, "content": {"membership": Membership.JOIN}, "room_id": room_id, "sender": user_id, @@ -492,7 +492,7 @@ class FederationHandler(BaseHandler): ) extra_users = [] - if event.type == RoomMemberEvent.TYPE: + if event.type == EventTypes.Member: target_user_id = event.state_key target_user = self.hs.parse_userid(target_user_id) extra_users.append(target_user) @@ -501,7 +501,7 @@ class FederationHandler(BaseHandler): event, extra_users=extra_users ) - if event.type == RoomMemberEvent.TYPE: + if event.type == EventTypes.Member: if event.content["membership"] == Membership.JOIN: user = self.hs.parse_userid(event.state_key) yield self.distributor.fire( @@ -514,7 +514,7 @@ class FederationHandler(BaseHandler): for k, s in context.current_state.items(): try: - if k[0] == RoomMemberEvent.TYPE: + if k[0] == EventTypes.Member: if s.content["membership"] == Membership.JOIN: destinations.add( self.hs.parse_userid(s.state_key).domain @@ -731,10 +731,10 @@ class FederationHandler(BaseHandler): event.event_id, event.signatures, ) - if event.type == RoomMemberEvent.TYPE and not event.auth_events: + if event.type == EventTypes.Member and not event.auth_events: if len(event.prev_events) == 1: c = yield self.store.get_event(event.prev_events[0][0]) - if c.type == RoomCreateEvent.TYPE: + if c.type == EventTypes.Create: context.auth_events[(c.type, c.state_key)] = c logger.debug( diff --git a/synapse/handlers/message.py b/synapse/handlers/message.py index 1eed38c6d1..baf372fdad 100644 --- a/synapse/handlers/message.py +++ b/synapse/handlers/message.py @@ -35,7 +35,6 @@ class MessageHandler(BaseHandler): super(MessageHandler, self).__init__(hs) self.hs = hs self.clock = hs.get_clock() - self.event_factory = hs.get_event_factory() self.validator = EventValidator() @defer.inlineCallbacks diff --git a/synapse/handlers/room.py b/synapse/handlers/room.py index f7cc869225..8567d7409d 100644 --- a/synapse/handlers/room.py +++ b/synapse/handlers/room.py @@ -17,12 +17,8 @@ from twisted.internet import defer from synapse.types import UserID, RoomAlias, RoomID -from synapse.api.constants import Membership, JoinRules +from synapse.api.constants import EventTypes, Membership, JoinRules from synapse.api.errors import StoreError, SynapseError -from synapse.api.events.room import ( - RoomMemberEvent, RoomCreateEvent, RoomPowerLevelsEvent, - RoomTopicEvent, RoomNameEvent, RoomJoinRulesEvent, -) from synapse.util import stringutils from synapse.util.async import run_on_reactor from ._base import BaseHandler @@ -131,7 +127,7 @@ class RoomCreationHandler(BaseHandler): if "name" in config: name = config["name"] yield msg_handler.create_and_send_event({ - "type": RoomNameEvent.TYPE, + "type": EventTypes.Name, "room_id": room_id, "sender": user_id, "content": {"name": name}, @@ -140,7 +136,7 @@ class RoomCreationHandler(BaseHandler): if "topic" in config: topic = config["topic"] yield msg_handler.create_and_send_event({ - "type": RoomTopicEvent.TYPE, + "type": EventTypes.Topic, "room_id": room_id, "sender": user_id, "content": {"topic": topic}, @@ -148,7 +144,7 @@ class RoomCreationHandler(BaseHandler): for invitee in invite_list: yield msg_handler.create_and_send_event({ - "type": RoomMemberEvent.TYPE, + "type": EventTypes.Member, "state_key": invitee, "room_id": room_id, "user_id": user_id, @@ -186,12 +182,12 @@ class RoomCreationHandler(BaseHandler): return e creation_event = create( - etype=RoomCreateEvent.TYPE, + etype=EventTypes.Create, content={"creator": creator.to_string()}, ) join_event = create( - etype=RoomMemberEvent.TYPE, + etype=EventTypes.Member, state_key=creator_id, content={ "membership": Membership.JOIN, @@ -199,15 +195,15 @@ class RoomCreationHandler(BaseHandler): ) power_levels_event = create( - etype=RoomPowerLevelsEvent.TYPE, + etype=EventTypes.PowerLevels, content={ "users": { creator.to_string(): 100, }, "users_default": 0, "events": { - RoomNameEvent.TYPE: 100, - RoomPowerLevelsEvent.TYPE: 100, + EventTypes.Name: 100, + EventTypes.PowerLevels: 100, }, "events_default": 0, "state_default": 50, @@ -219,7 +215,7 @@ class RoomCreationHandler(BaseHandler): join_rule = JoinRules.PUBLIC if is_public else JoinRules.INVITE join_rules_event = create( - etype=RoomJoinRulesEvent.TYPE, + etype=EventTypes.JoinRules, content={"join_rule": join_rule}, ) @@ -344,7 +340,7 @@ class RoomMemberHandler(BaseHandler): target_user_id = event.state_key prev_state = context.current_state.get( - (RoomMemberEvent.TYPE, target_user_id), + (EventTypes.Member, target_user_id), None ) @@ -396,7 +392,7 @@ class RoomMemberHandler(BaseHandler): content.update({"membership": Membership.JOIN}) builder = self.event_builder_factory.new({ - "type": RoomMemberEvent.TYPE, + "type": EventTypes.Member, "state_key": joinee.to_string(), "room_id": room_id, "sender": joinee.to_string(), diff --git a/synapse/rest/__init__.py b/synapse/rest/__init__.py index e391e5678d..a59630ec96 100644 --- a/synapse/rest/__init__.py +++ b/synapse/rest/__init__.py @@ -28,7 +28,7 @@ class RestServletFactory(object): speaking, they serve as wrappers around events and the handlers that process them. - See synapse.api.events for information on synapse events. + See synapse.events for information on synapse events. """ def __init__(self, hs): diff --git a/synapse/rest/base.py b/synapse/rest/base.py index 72bb66ddda..06eda2587c 100644 --- a/synapse/rest/base.py +++ b/synapse/rest/base.py @@ -67,8 +67,6 @@ class RestServlet(object): self.auth = hs.get_auth() self.txns = HttpTransactionStore() - self.validator = hs.get_event_validator() - def register(self, http_server): """ Register this servlet with the given HTTP server. """ if hasattr(self, "PATTERN"): diff --git a/synapse/rest/room.py b/synapse/rest/room.py index 1a527d27c1..0e2d5fbaae 100644 --- a/synapse/rest/room.py +++ b/synapse/rest/room.py @@ -19,8 +19,7 @@ from twisted.internet import defer from base import RestServlet, client_path_pattern from synapse.api.errors import SynapseError, Codes from synapse.streams.config import PaginationConfig -from synapse.api.events.room import RoomMemberEvent, RoomRedactionEvent -from synapse.api.constants import Membership +from synapse.api.constants import EventTypes, Membership import json import logging @@ -239,7 +238,7 @@ class JoinRoomAliasServlet(RestServlet): msg_handler = self.handlers.message_handler yield msg_handler.create_and_send_event( { - "type": RoomMemberEvent.TYPE, + "type": EventTypes.Member, "content": {"membership": Membership.JOIN}, "room_id": identifier.to_string(), "sender": user.to_string(), @@ -403,7 +402,7 @@ class RoomMembershipRestServlet(RestServlet): msg_handler = self.handlers.message_handler yield msg_handler.create_and_send_event( { - "type": RoomMemberEvent.TYPE, + "type": EventTypes.Member, "content": {"membership": unicode(membership_action)}, "room_id": room_id, "sender": user.to_string(), @@ -441,7 +440,7 @@ class RoomRedactEventRestServlet(RestServlet): msg_handler = self.handlers.message_handler event = yield msg_handler.create_and_send_event( { - "type": RoomRedactionEvent.TYPE, + "type": EventTypes.Redaction, "content": content, "room_id": room_id, "sender": user.to_string(), diff --git a/synapse/server.py b/synapse/server.py index 1c0703c51f..e4021481e8 100644 --- a/synapse/server.py +++ b/synapse/server.py @@ -21,8 +21,6 @@ # Imports required for the default HomeServer() implementation from synapse.federation import initialize_http_replication from synapse.events.utils import serialize_event -from synapse.api.events.factory import EventFactory -from synapse.api.events.validator import EventValidator from synapse.notifier import Notifier from synapse.api.auth import Auth from synapse.handlers import Handlers @@ -66,7 +64,6 @@ class BaseHomeServer(object): 'persistence_service', 'replication_layer', 'datastore', - 'event_factory', 'handlers', 'auth', 'rest_servlet_factory', @@ -83,7 +80,6 @@ class BaseHomeServer(object): 'event_sources', 'ratelimiter', 'keyring', - 'event_validator', 'event_builder_factory', ] @@ -198,9 +194,6 @@ class HomeServer(BaseHomeServer): def build_datastore(self): return DataStore(self) - def build_event_factory(self): - return EventFactory(self) - def build_handlers(self): return Handlers(self) @@ -231,9 +224,6 @@ class HomeServer(BaseHomeServer): def build_keyring(self): return Keyring(self) - def build_event_validator(self): - return EventValidator(self) - def build_event_builder_factory(self): return EventBuilderFactory( clock=self.get_clock(), diff --git a/synapse/state.py b/synapse/state.py index f9ab5faf9e..d2763cdd9a 100644 --- a/synapse/state.py +++ b/synapse/state.py @@ -18,7 +18,7 @@ from twisted.internet import defer from synapse.util.logutils import log_function from synapse.util.async import run_on_reactor -from synapse.api.events.room import RoomPowerLevelsEvent +from synapse.api.constants import EventTypes from collections import namedtuple @@ -271,7 +271,7 @@ class StateHandler(object): def _get_power_level_from_event_state(self, event, user_id): if hasattr(event, "old_state_events") and event.old_state_events: - key = (RoomPowerLevelsEvent.TYPE, "", ) + key = (EventTypes.PowerLevels, "", ) power_level_event = event.old_state_events.get(key) level = None if power_level_event: diff --git a/synapse/storage/__init__.py b/synapse/storage/__init__.py index e75eaa92d5..5c079da5ba 100644 --- a/synapse/storage/__init__.py +++ b/synapse/storage/__init__.py @@ -15,12 +15,8 @@ from twisted.internet import defer -from synapse.api.events.room import ( - RoomMemberEvent, RoomTopicEvent, FeedbackEvent, RoomNameEvent, - RoomRedactionEvent, -) - from synapse.util.logutils import log_function +from synapse.api.constants import EventTypes from .directory import DirectoryStore from .feedback import FeedbackStore @@ -136,15 +132,15 @@ class DataStore(RoomMemberStore, RoomStore, def _persist_event_txn(self, txn, event, context, backfilled, stream_ordering=None, is_new_state=True, current_state=None): - if event.type == RoomMemberEvent.TYPE: + if event.type == EventTypes.Member: self._store_room_member_txn(txn, event) - elif event.type == FeedbackEvent.TYPE: + elif event.type == EventTypes.Feedback: self._store_feedback_txn(txn, event) - elif event.type == RoomNameEvent.TYPE: + elif event.type == EventTypes.Name: self._store_room_name_txn(txn, event) - elif event.type == RoomTopicEvent.TYPE: + elif event.type == EventTypes.Topic: self._store_room_topic_txn(txn, event) - elif event.type == RoomRedactionEvent.TYPE: + elif event.type == EventTypes.Redaction: self._store_redaction(txn, event) outlier = False diff --git a/tests/events/__init__.py b/tests/events/__init__.py deleted file mode 100644 index 9bff9ec169..0000000000 --- a/tests/events/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -# -*- coding: utf-8 -*- -# 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. - diff --git a/tests/events/test_events.py b/tests/events/test_events.py deleted file mode 100644 index 91d1d44fee..0000000000 --- a/tests/events/test_events.py +++ /dev/null @@ -1,217 +0,0 @@ -# -*- coding: utf-8 -*- -# 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. - -from synapse.api.events import SynapseEvent -from synapse.api.events.validator import EventValidator -from synapse.api.errors import SynapseError - -from tests import unittest - - -class SynapseTemplateCheckTestCase(unittest.TestCase): - - def setUp(self): - self.validator = EventValidator(None) - - def tearDown(self): - pass - - def test_top_level_keys(self): - template = { - "person": {}, - "friends": ["string"] - } - - content = { - "person": {"name": "bob"}, - "friends": ["jill", "mike"] - } - - event = MockSynapseEvent(template) - event.content = content - self.assertTrue(self.validator.validate(event)) - - content = { - "person": {"name": "bob"}, - "friends": ["jill"], - "enemies": ["mike"] - } - event.content = content - self.assertTrue(self.validator.validate(event)) - - content = { - "person": {"name": "bob"}, - # missing friends - "enemies": ["mike", "jill"] - } - event.content = content - self.assertRaises( - SynapseError, - self.validator.validate, - event - ) - - def test_lists(self): - template = { - "person": {}, - "friends": [{"name":"string"}] - } - - content = { - "person": {"name": "bob"}, - "friends": ["jill", "mike"] # should be in objects - } - - event = MockSynapseEvent(template) - event.content = content - self.assertRaises( - SynapseError, - self.validator.validate, - event - ) - - content = { - "person": {"name": "bob"}, - "friends": [{"name": "jill"}, {"name": "mike"}] - } - event.content = content - self.assertTrue(self.validator.validate(event)) - - def test_nested_lists(self): - template = { - "results": { - "families": [ - { - "name": "string", - "members": [ - {} - ] - } - ] - } - } - - content = { - "results": { - "families": [ - { - "name": "Smith", - "members": [ - "Alice", "Bob" # wrong types - ] - } - ] - } - } - - event = MockSynapseEvent(template) - event.content = content - self.assertRaises( - SynapseError, - self.validator.validate, - event - ) - - content = { - "results": { - "families": [ - { - "name": "Smith", - "members": [ - {"name": "Alice"}, {"name": "Bob"} - ] - } - ] - } - } - event.content = content - self.assertTrue(self.validator.validate(event)) - - def test_nested_keys(self): - template = { - "person": { - "attributes": { - "hair": "string", - "eye": "string" - }, - "age": 0, - "fav_books": ["string"] - } - } - event = MockSynapseEvent(template) - - content = { - "person": { - "attributes": { - "hair": "brown", - "eye": "green", - "skin": "purple" - }, - "age": 33, - "fav_books": ["lotr", "hobbit"], - "fav_music": ["abba", "beatles"] - } - } - - event.content = content - self.assertTrue(self.validator.validate(event)) - - content = { - "person": { - "attributes": { - "hair": "brown" - # missing eye - }, - "age": 33, - "fav_books": ["lotr", "hobbit"], - "fav_music": ["abba", "beatles"] - } - } - - event.content = content - self.assertRaises( - SynapseError, - self.validator.validate, - event - ) - - content = { - "person": { - "attributes": { - "hair": "brown", - "eye": "green", - "skin": "purple" - }, - "age": 33, - "fav_books": "nothing", # should be a list - } - } - - event.content = content - self.assertRaises( - SynapseError, - self.validator.validate, - event - ) - - -class MockSynapseEvent(SynapseEvent): - - def __init__(self, template): - self.template = template - - def get_content_template(self): - return self.template - diff --git a/tests/handlers/test_federation.py b/tests/handlers/test_federation.py index 91f7351087..ed351367cc 100644 --- a/tests/handlers/test_federation.py +++ b/tests/handlers/test_federation.py @@ -16,10 +16,7 @@ from twisted.internet import defer from tests import unittest -from synapse.api.events.room import ( - MessageEvent, -) - +from synapse.api.constants import EventTypes from synapse.events import FrozenEvent from synapse.handlers.federation import FederationHandler from synapse.server import HomeServer @@ -79,7 +76,7 @@ class FederationTestCase(unittest.TestCase): @defer.inlineCallbacks def test_msg(self): pdu = FrozenEvent({ - "type": MessageEvent.TYPE, + "type": EventTypes.Message, "room_id": "foo", "content": {"msgtype": u"fooo"}, "origin_server_ts": 0, diff --git a/tests/handlers/test_room.py b/tests/handlers/test_room.py index 9c63f2a882..83493cae20 100644 --- a/tests/handlers/test_room.py +++ b/tests/handlers/test_room.py @@ -17,9 +17,6 @@ from twisted.internet import defer from tests import unittest -from synapse.api.events.room import ( - RoomMemberEvent, -) from synapse.api.constants import EventTypes, Membership from synapse.handlers.room import RoomMemberHandler, RoomCreationHandler from synapse.handlers.profile import ProfileHandler @@ -102,7 +99,7 @@ class RoomMemberHandlerTestCase(unittest.TestCase): content = {"membership": Membership.INVITE} builder = self.hs.get_event_builder_factory().new({ - "type": RoomMemberEvent.TYPE, + "type": EventTypes.Member, "sender": user_id, "state_key": target_user_id, "room_id": room_id, @@ -115,11 +112,11 @@ class RoomMemberHandlerTestCase(unittest.TestCase): def annotate(_, ctx): ctx.current_state = { - (RoomMemberEvent.TYPE, "@alice:green"): self._create_member( + (EventTypes.Member, "@alice:green"): self._create_member( user_id="@alice:green", room_id=room_id, ), - (RoomMemberEvent.TYPE, "@bob:red"): self._create_member( + (EventTypes.Member, "@bob:red"): self._create_member( user_id="@bob:red", room_id=room_id, ), @@ -131,7 +128,7 @@ class RoomMemberHandlerTestCase(unittest.TestCase): def add_auth(_, ctx): ctx.auth_events = ctx.current_state[ - (RoomMemberEvent.TYPE, "@bob:red") + (EventTypes.Member, "@bob:red") ] return defer.succeed(True) @@ -181,7 +178,7 @@ class RoomMemberHandlerTestCase(unittest.TestCase): self.distributor.observe("user_joined_room", join_signal_observer) builder = self.hs.get_event_builder_factory().new({ - "type": RoomMemberEvent.TYPE, + "type": EventTypes.Member, "sender": user_id, "state_key": user_id, "room_id": room_id, @@ -194,7 +191,7 @@ class RoomMemberHandlerTestCase(unittest.TestCase): def annotate(_, ctx): ctx.current_state = { - (RoomMemberEvent.TYPE, "@bob:red"): self._create_member( + (EventTypes.Member, "@bob:red"): self._create_member( user_id="@bob:red", room_id=room_id, membership=Membership.INVITE @@ -207,7 +204,7 @@ class RoomMemberHandlerTestCase(unittest.TestCase): def add_auth(_, ctx): ctx.auth_events = ctx.current_state[ - (RoomMemberEvent.TYPE, "@bob:red") + (EventTypes.Member, "@bob:red") ] return defer.succeed(True) @@ -238,7 +235,7 @@ class RoomMemberHandlerTestCase(unittest.TestCase): def _create_member(self, user_id, room_id, membership=Membership.JOIN): builder = self.hs.get_event_builder_factory().new({ - "type": RoomMemberEvent.TYPE, + "type": EventTypes.Member, "sender": user_id, "state_key": user_id, "room_id": room_id, @@ -254,7 +251,7 @@ class RoomMemberHandlerTestCase(unittest.TestCase): user = self.hs.parse_userid(user_id) builder = self.hs.get_event_builder_factory().new({ - "type": RoomMemberEvent.TYPE, + "type": EventTypes.Member, "sender": user_id, "state_key": user_id, "room_id": room_id, @@ -267,7 +264,7 @@ class RoomMemberHandlerTestCase(unittest.TestCase): def annotate(_, ctx): ctx.current_state = { - (RoomMemberEvent.TYPE, "@bob:red"): self._create_member( + (EventTypes.Member, "@bob:red"): self._create_member( user_id="@bob:red", room_id=room_id, membership=Membership.JOIN @@ -280,7 +277,7 @@ class RoomMemberHandlerTestCase(unittest.TestCase): def add_auth(_, ctx): ctx.auth_events = ctx.current_state[ - (RoomMemberEvent.TYPE, "@bob:red") + (EventTypes.Member, "@bob:red") ] return defer.succeed(True) diff --git a/tests/storage/test_redaction.py b/tests/storage/test_redaction.py index f670e154c3..9806fbc69b 100644 --- a/tests/storage/test_redaction.py +++ b/tests/storage/test_redaction.py @@ -18,10 +18,7 @@ from tests import unittest from twisted.internet import defer from synapse.server import HomeServer -from synapse.api.constants import Membership -from synapse.api.events.room import ( - RoomMemberEvent, MessageEvent, RoomRedactionEvent, -) +from synapse.api.constants import EventTypes, Membership from tests.utils import SQLiteMemoryDbPool, MockKey @@ -64,7 +61,7 @@ class RedactionTestCase(unittest.TestCase): content = {"membership": membership} content.update(extra_content) builder = self.event_builder_factory.new({ - "type": RoomMemberEvent.TYPE, + "type": EventTypes.Member, "sender": user.to_string(), "state_key": user.to_string(), "room_id": room.to_string(), @@ -84,7 +81,7 @@ class RedactionTestCase(unittest.TestCase): self.depth += 1 builder = self.event_builder_factory.new({ - "type": MessageEvent.TYPE, + "type": EventTypes.Message, "sender": user.to_string(), "state_key": user.to_string(), "room_id": room.to_string(), @@ -102,7 +99,7 @@ class RedactionTestCase(unittest.TestCase): @defer.inlineCallbacks def inject_redaction(self, room, event_id, user, reason): builder = self.event_builder_factory.new({ - "type": RoomRedactionEvent.TYPE, + "type": EventTypes.Redaction, "sender": user.to_string(), "state_key": user.to_string(), "room_id": room.to_string(), @@ -142,7 +139,7 @@ class RedactionTestCase(unittest.TestCase): self.assertObjectHasAttributes( { - "type": MessageEvent.TYPE, + "type": EventTypes.Message, "user_id": self.u_alice.to_string(), "content": {"body": "t", "msgtype": "message"}, }, @@ -176,7 +173,7 @@ class RedactionTestCase(unittest.TestCase): self.assertObjectHasAttributes( { - "type": MessageEvent.TYPE, + "type": EventTypes.Message, "user_id": self.u_alice.to_string(), "content": {}, }, @@ -185,7 +182,7 @@ class RedactionTestCase(unittest.TestCase): self.assertObjectHasAttributes( { - "type": RoomRedactionEvent.TYPE, + "type": EventTypes.Redaction, "user_id": self.u_alice.to_string(), "content": {"reason": reason}, }, @@ -221,7 +218,7 @@ class RedactionTestCase(unittest.TestCase): self.assertObjectHasAttributes( { - "type": RoomMemberEvent.TYPE, + "type": EventTypes.Member, "user_id": self.u_bob.to_string(), "content": {"membership": Membership.JOIN, "blue": "red"}, }, @@ -253,7 +250,7 @@ class RedactionTestCase(unittest.TestCase): self.assertObjectHasAttributes( { - "type": RoomMemberEvent.TYPE, + "type": EventTypes.Member, "user_id": self.u_bob.to_string(), "content": {"membership": Membership.JOIN}, }, @@ -262,7 +259,7 @@ class RedactionTestCase(unittest.TestCase): self.assertObjectHasAttributes( { - "type": RoomRedactionEvent.TYPE, + "type": EventTypes.Redaction, "user_id": self.u_alice.to_string(), "content": {"reason": reason}, }, diff --git a/tests/storage/test_room.py b/tests/storage/test_room.py index 4ff02c306b..11761fe29a 100644 --- a/tests/storage/test_room.py +++ b/tests/storage/test_room.py @@ -18,9 +18,7 @@ from tests import unittest from twisted.internet import defer from synapse.server import HomeServer -from synapse.api.events.room import ( - RoomNameEvent, RoomTopicEvent -) +from synapse.api.constants import EventTypes from tests.utils import SQLiteMemoryDbPool @@ -131,7 +129,7 @@ class RoomEventsStoreTestCase(unittest.TestCase): name = u"A-Room-Name" yield self.inject_room_event( - etype=RoomNameEvent.TYPE, + etype=EventTypes.Name, name=name, content={"name": name}, depth=1, @@ -154,7 +152,7 @@ class RoomEventsStoreTestCase(unittest.TestCase): topic = u"A place for things" yield self.inject_room_event( - etype=RoomTopicEvent.TYPE, + etype=EventTypes.Topic, topic=topic, content={"topic": topic}, depth=1, diff --git a/tests/storage/test_roommember.py b/tests/storage/test_roommember.py index 6df09952d1..a23a8189df 100644 --- a/tests/storage/test_roommember.py +++ b/tests/storage/test_roommember.py @@ -18,8 +18,7 @@ from tests import unittest from twisted.internet import defer from synapse.server import HomeServer -from synapse.api.constants import Membership -from synapse.api.events.room import RoomMemberEvent +from synapse.api.constants import EventTypes, Membership from tests.utils import SQLiteMemoryDbPool, MockKey @@ -61,7 +60,7 @@ class RoomMemberStoreTestCase(unittest.TestCase): @defer.inlineCallbacks def inject_room_member(self, room, user, membership, replaces_state=None): builder = self.event_builder_factory.new({ - "type": RoomMemberEvent.TYPE, + "type": EventTypes.Member, "sender": user.to_string(), "state_key": user.to_string(), "room_id": room.to_string(), diff --git a/tests/storage/test_stream.py b/tests/storage/test_stream.py index 4865a5c142..9247fc579e 100644 --- a/tests/storage/test_stream.py +++ b/tests/storage/test_stream.py @@ -18,8 +18,7 @@ from tests import unittest from twisted.internet import defer from synapse.server import HomeServer -from synapse.api.constants import Membership -from synapse.api.events.room import RoomMemberEvent, MessageEvent +from synapse.api.constants import EventTypes, Membership from tests.utils import SQLiteMemoryDbPool, MockKey @@ -62,7 +61,7 @@ class StreamStoreTestCase(unittest.TestCase): self.depth += 1 builder = self.event_builder_factory.new({ - "type": RoomMemberEvent.TYPE, + "type": EventTypes.Member, "sender": user.to_string(), "state_key": user.to_string(), "room_id": room.to_string(), @@ -82,7 +81,7 @@ class StreamStoreTestCase(unittest.TestCase): self.depth += 1 builder = self.event_builder_factory.new({ - "type": MessageEvent.TYPE, + "type": EventTypes.Message, "sender": user.to_string(), "state_key": user.to_string(), "room_id": room.to_string(), @@ -125,7 +124,7 @@ class StreamStoreTestCase(unittest.TestCase): self.assertObjectHasAttributes( { - "type": MessageEvent.TYPE, + "type": EventTypes.Message, "user_id": self.u_alice.to_string(), "content": {"body": "test", "msgtype": "message"}, }, @@ -162,7 +161,7 @@ class StreamStoreTestCase(unittest.TestCase): self.assertObjectHasAttributes( { - "type": MessageEvent.TYPE, + "type": EventTypes.Message, "user_id": self.u_alice.to_string(), "content": {"body": "test", "msgtype": "message"}, }, diff --git a/tests/utils.py b/tests/utils.py index 70a221550c..731e03f517 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -15,15 +15,11 @@ from synapse.http.server import HttpServer from synapse.api.errors import cs_error, CodeMessageException, StoreError -from synapse.api.constants import Membership +from synapse.api.constants import EventTypes from synapse.storage import prepare_database from synapse.util.logcontext import LoggingContext -from synapse.api.events.room import ( - RoomMemberEvent, MessageEvent -) - from twisted.internet import defer, reactor from twisted.enterprise.adbapi import ConnectionPool @@ -276,7 +272,7 @@ class MemoryDataStore(object): return defer.succeed([]) def persist_event(self, event): - if event.type == RoomMemberEvent.TYPE: + if event.type == EventTypes.Member: room_id = event.room_id user = event.state_key membership = event.membership -- cgit 1.5.1 From 8b8beba194f45b171345a44d4b42841d5e7311d3 Mon Sep 17 00:00:00 2001 From: Mark Haines Date: Tue, 16 Dec 2014 15:07:38 +0000 Subject: Remove annotate_event_with_state as nothing was using it. Update state tests to call annotate_context_with_state --- synapse/state.py | 66 -------------------------------- tests/test_state.py | 108 +++++++++++++++++++--------------------------------- 2 files changed, 39 insertions(+), 135 deletions(-) (limited to 'tests') diff --git a/synapse/state.py b/synapse/state.py index 38adde4dc9..61b14b939f 100644 --- a/synapse/state.py +++ b/synapse/state.py @@ -22,7 +22,6 @@ from synapse.api.constants import EventTypes from collections import namedtuple -import copy import logging import hashlib @@ -43,71 +42,6 @@ class StateHandler(object): def __init__(self, hs): self.store = hs.get_datastore() - @defer.inlineCallbacks - @log_function - def annotate_event_with_state(self, event, old_state=None): - """ Annotates the event with the current state events as of that event. - - This method adds three new attributes to the event: - * `state_events`: The state up to and including the event. Encoded - as a dict mapping tuple (type, state_key) -> event. - * `old_state_events`: The state up to, but excluding, the event. - Encoded similarly as `state_events`. - * `state_group`: If there is an existing state group that can be - used, then return that. Otherwise return `None`. See state - storage for more information. - - If the argument `old_state` is given (in the form of a list of - events), then they are used as a the values for `old_state_events` and - the value for `state_events` is generated from it. `state_group` is - set to None. - - This needs to be called before persisting the event. - """ - yield run_on_reactor() - - if old_state: - event.state_group = None - event.old_state_events = { - (s.type, s.state_key): s for s in old_state - } - event.state_events = event.old_state_events - - if hasattr(event, "state_key"): - event.state_events[(event.type, event.state_key)] = event - - defer.returnValue(False) - return - - if hasattr(event, "outlier") and event.outlier: - event.state_group = None - event.old_state_events = None - event.state_events = None - defer.returnValue(False) - return - - ids = [e for e, _ in event.prev_events] - - ret = yield self.resolve_state_groups(ids) - state_group, new_state, _ = ret - - event.old_state_events = copy.deepcopy(new_state) - - if hasattr(event, "state_key"): - key = (event.type, event.state_key) - if key in new_state: - event.replaces_state = new_state[key].event_id - new_state[key] = event - elif state_group: - event.state_group = state_group - event.state_events = new_state - defer.returnValue(False) - - event.state_group = None - event.state_events = new_state - - defer.returnValue(hasattr(event, "state_key")) - @defer.inlineCallbacks def get_current_state(self, room_id, event_type=None, state_key=""): """ Returns the current state for the room as a list. This is done by diff --git a/tests/test_state.py b/tests/test_state.py index 7979b54a35..197e35f140 100644 --- a/tests/test_state.py +++ b/tests/test_state.py @@ -26,6 +26,7 @@ class StateTestCase(unittest.TestCase): self.store = Mock( spec_set=[ "get_state_groups", + "add_event_hashes", ] ) hs = Mock(spec=["get_datastore"]) @@ -37,6 +38,7 @@ class StateTestCase(unittest.TestCase): @defer.inlineCallbacks def test_annotate_with_old_message(self): event = self.create_event(type="test_message", name="event") + context = Mock() old_state = [ self.create_event(type="test1", state_key="1"), @@ -44,21 +46,25 @@ class StateTestCase(unittest.TestCase): self.create_event(type="test2", state_key=""), ] - yield self.state.annotate_event_with_state(event, old_state=old_state) + yield self.state.annotate_context_with_state( + event, context, old_state=old_state + ) - for k, v in event.old_state_events.items(): + for k, v in context.current_state.items(): type, state_key = k self.assertEqual(type, v.type) self.assertEqual(state_key, v.state_key) - self.assertEqual(set(old_state), set(event.old_state_events.values())) - self.assertDictEqual(event.old_state_events, event.state_events) + self.assertEqual( + set(old_state), set(context.current_state.values()) + ) - self.assertIsNone(event.state_group) + self.assertIsNone(context.state_group) @defer.inlineCallbacks def test_annotate_with_old_state(self): event = self.create_event(type="state", state_key="", name="event") + context = Mock() old_state = [ self.create_event(type="test1", state_key="1"), @@ -66,26 +72,27 @@ class StateTestCase(unittest.TestCase): self.create_event(type="test2", state_key=""), ] - yield self.state.annotate_event_with_state(event, old_state=old_state) + yield self.state.annotate_context_with_state( + event, context, old_state=old_state + ) - for k, v in event.old_state_events.items(): + for k, v in context.current_state.items(): type, state_key = k self.assertEqual(type, v.type) self.assertEqual(state_key, v.state_key) self.assertEqual( - set(old_state + [event]), - set(event.old_state_events.values()) + set(old_state), + set(context.current_state.values()) ) - self.assertDictEqual(event.old_state_events, event.state_events) - - self.assertIsNone(event.state_group) + self.assertIsNone(context.state_group) @defer.inlineCallbacks def test_trivial_annotate_message(self): event = self.create_event(type="test_message", name="event") event.prev_events = [] + context = Mock() old_state = [ self.create_event(type="test1", state_key="1"), @@ -99,35 +106,25 @@ class StateTestCase(unittest.TestCase): group_name: old_state, } - yield self.state.annotate_event_with_state(event) + yield self.state.annotate_context_with_state(event, context) - for k, v in event.old_state_events.items(): + for k, v in context.current_state.items(): type, state_key = k self.assertEqual(type, v.type) self.assertEqual(state_key, v.state_key) self.assertEqual( set([e.event_id for e in old_state]), - set([e.event_id for e in event.old_state_events.values()]) + set([e.event_id for e in context.current_state.values()]) ) - self.assertDictEqual( - { - k: v.event_id - for k, v in event.old_state_events.items() - }, - { - k: v.event_id - for k, v in event.state_events.items() - } - ) - - self.assertEqual(group_name, event.state_group) + self.assertEqual(group_name, context.state_group) @defer.inlineCallbacks def test_trivial_annotate_state(self): event = self.create_event(type="state", state_key="", name="event") event.prev_events = [] + context = Mock() old_state = [ self.create_event(type="test1", state_key="1"), @@ -141,43 +138,25 @@ class StateTestCase(unittest.TestCase): group_name: old_state, } - yield self.state.annotate_event_with_state(event) + yield self.state.annotate_context_with_state(event, context) - for k, v in event.old_state_events.items(): + for k, v in context.current_state.items(): type, state_key = k self.assertEqual(type, v.type) self.assertEqual(state_key, v.state_key) self.assertEqual( set([e.event_id for e in old_state]), - set([e.event_id for e in event.old_state_events.values()]) - ) - - self.assertEqual( - set([e.event_id for e in old_state] + [event.event_id]), - set([e.event_id for e in event.state_events.values()]) - ) - - new_state = { - k: v.event_id - for k, v in event.state_events.items() - } - old_state = { - k: v.event_id - for k, v in event.old_state_events.items() - } - old_state[(event.type, event.state_key)] = event.event_id - self.assertDictEqual( - old_state, - new_state + set([e.event_id for e in context.current_state.values()]) ) - self.assertIsNone(event.state_group) + self.assertIsNone(context.state_group) @defer.inlineCallbacks def test_resolve_message_conflict(self): event = self.create_event(type="test_message", name="event") event.prev_events = [] + context = Mock() old_state_1 = [ self.create_event(type="test1", state_key="1"), @@ -199,21 +178,17 @@ class StateTestCase(unittest.TestCase): group_name_2: old_state_2, } - yield self.state.annotate_event_with_state(event) + yield self.state.annotate_context_with_state(event, context) - self.assertEqual(len(event.old_state_events), 5) - - self.assertEqual( - set([e.event_id for e in event.state_events.values()]), - set([e.event_id for e in event.old_state_events.values()]) - ) + self.assertEqual(len(context.current_state), 5) - self.assertIsNone(event.state_group) + self.assertIsNone(context.state_group) @defer.inlineCallbacks def test_resolve_state_conflict(self): event = self.create_event(type="test4", state_key="", name="event") event.prev_events = [] + context = Mock() old_state_1 = [ self.create_event(type="test1", state_key="1"), @@ -235,19 +210,11 @@ class StateTestCase(unittest.TestCase): group_name_2: old_state_2, } - yield self.state.annotate_event_with_state(event) + yield self.state.annotate_context_with_state(event, context) - self.assertEqual(len(event.old_state_events), 5) + self.assertEqual(len(context.current_state), 5) - expected_new = event.old_state_events - expected_new[(event.type, event.state_key)] = event - - self.assertEqual( - set([e.event_id for e in expected_new.values()]), - set([e.event_id for e in event.state_events.values()]), - ) - - self.assertIsNone(event.state_group) + self.assertIsNone(context.state_group) def create_event(self, name=None, type=None, state_key=None): self.event_id += 1 @@ -266,6 +233,9 @@ class StateTestCase(unittest.TestCase): event.state_key = state_key event.event_id = event_id + event.is_state = lambda: (state_key is not None) + event.unsigned = {} + event.user_id = "@user_id:example.com" event.room_id = "!room_id:example.com" -- cgit 1.5.1 From c3eae8a88c21cf99b0109ebcb3f0f49714617060 Mon Sep 17 00:00:00 2001 From: Mark Haines Date: Tue, 16 Dec 2014 15:59:17 +0000 Subject: Construct the EventContext in the state handler rather than constructing one and then immediately calling state_handler.annotate_context_with_state --- synapse/handlers/_base.py | 11 ++--------- synapse/handlers/federation.py | 14 ++++---------- synapse/state.py | 14 ++++++++++---- tests/handlers/test_federation.py | 18 ++++++++---------- tests/handlers/test_room.py | 30 ++++++++++++++++++------------ tests/test_state.py | 22 ++++++++-------------- 6 files changed, 50 insertions(+), 59 deletions(-) (limited to 'tests') diff --git a/synapse/handlers/_base.py b/synapse/handlers/_base.py index 567769253e..97ebd98917 100644 --- a/synapse/handlers/_base.py +++ b/synapse/handlers/_base.py @@ -20,8 +20,6 @@ from synapse.util.async import run_on_reactor from synapse.crypto.event_signing import add_hashes_and_signatures from synapse.api.constants import Membership, EventTypes -from synapse.events.snapshot import EventContext - import logging @@ -77,15 +75,10 @@ class BaseHandler(object): state_handler = self.state_handler - context = EventContext() - ret = yield state_handler.annotate_context_with_state( - builder, - context, - ) - prev_state = ret + context = yield state_handler.compute_event_context(builder) if builder.is_state(): - builder.prev_state = prev_state + builder.prev_state = context.prev_state_events yield self.auth.add_auth_events(builder, context) diff --git a/synapse/handlers/federation.py b/synapse/handlers/federation.py index d80a54bdea..4aec3563ac 100644 --- a/synapse/handlers/federation.py +++ b/synapse/handlers/federation.py @@ -17,7 +17,6 @@ from ._base import BaseHandler -from synapse.events.snapshot import EventContext from synapse.events.utils import prune_event from synapse.api.errors import ( AuthError, FederationError, SynapseError, StoreError, @@ -260,8 +259,7 @@ class FederationHandler(BaseHandler): event = pdu # FIXME (erikj): Not sure this actually works :/ - context = EventContext() - yield self.state_handler.annotate_context_with_state(event, context) + context = yield self.state_handler.compute_event_context(event) events.append((event, context)) @@ -555,8 +553,7 @@ class FederationHandler(BaseHandler): ) ) - context = EventContext() - yield self.state_handler.annotate_context_with_state(event, context) + context = yield self.state_handler.compute_event_context(event) yield self.store.persist_event( event, @@ -688,11 +685,8 @@ class FederationHandler(BaseHandler): event.event_id, event.signatures, ) - context = EventContext() - yield self.state_handler.annotate_context_with_state( - event, - context, - old_state=state + context = yield self.state_handler.compute_event_context( + event, old_state=state ) logger.debug( diff --git a/synapse/state.py b/synapse/state.py index 61b14b939f..551058b510 100644 --- a/synapse/state.py +++ b/synapse/state.py @@ -19,6 +19,7 @@ from twisted.internet import defer from synapse.util.logutils import log_function from synapse.util.async import run_on_reactor from synapse.api.constants import EventTypes +from synapse.events.snapshot import EventContext from collections import namedtuple @@ -70,7 +71,7 @@ class StateHandler(object): defer.returnValue(res[1].values()) @defer.inlineCallbacks - def annotate_context_with_state(self, event, context, old_state=None): + def compute_event_context(self, event, old_state=None): """ Fills out the context with the `current state` of the graph. The `current state` here is defined to be the state of the event graph just before the event - i.e. it never includes `event` @@ -80,8 +81,11 @@ class StateHandler(object): Args: event (EventBase) - context (EventContext) + Returns: + an EventContext """ + context = EventContext() + yield run_on_reactor() if old_state: @@ -107,7 +111,8 @@ class StateHandler(object): if replaces.event_id != event.event_id: # Paranoia check event.unsigned["replaces_state"] = replaces.event_id - defer.returnValue([]) + context.prev_state_events = [] + defer.returnValue(context) if event.is_state(): ret = yield self.resolve_state_groups( @@ -145,7 +150,8 @@ class StateHandler(object): else: context.auth_events = {} - defer.returnValue(prev_state) + context.prev_state_events = prev_state + defer.returnValue(context) @defer.inlineCallbacks @log_function diff --git a/tests/handlers/test_federation.py b/tests/handlers/test_federation.py index ed351367cc..ed21defd13 100644 --- a/tests/handlers/test_federation.py +++ b/tests/handlers/test_federation.py @@ -34,7 +34,7 @@ class FederationTestCase(unittest.TestCase): self.mock_config.signing_key = [MockKey()] self.state_handler = NonCallableMock(spec_set=[ - "annotate_context_with_state", + "compute_event_context", ]) self.auth = NonCallableMock(spec_set=[ @@ -91,11 +91,12 @@ class FederationTestCase(unittest.TestCase): self.datastore.get_room.return_value = defer.succeed(True) self.auth.check_host_in_room.return_value = defer.succeed(True) - def annotate(ev, context, old_state=None): + def annotate(ev, old_state=None): + context = Mock() context.current_state = {} context.auth_events = {} - return defer.succeed(False) - self.state_handler.annotate_context_with_state.side_effect = annotate + return defer.succeed(context) + self.state_handler.compute_event_context.side_effect = annotate yield self.handlers.federation_handler.on_receive_pdu( "fo", pdu, False @@ -109,15 +110,12 @@ class FederationTestCase(unittest.TestCase): context=ANY, ) - self.state_handler.annotate_context_with_state.assert_called_once_with( - ANY, - ANY, - old_state=None, + self.state_handler.compute_event_context.assert_called_once_with( + ANY, old_state=None, ) self.auth.check.assert_called_once_with(ANY, auth_events={}) self.notifier.on_new_room_event.assert_called_once_with( - ANY, - extra_users=[] + ANY, extra_users=[] ) diff --git a/tests/handlers/test_room.py b/tests/handlers/test_room.py index 83493cae20..0cb8aa4fbc 100644 --- a/tests/handlers/test_room.py +++ b/tests/handlers/test_room.py @@ -60,7 +60,7 @@ class RoomMemberHandlerTestCase(unittest.TestCase): "check_host_in_room", ]), state_handler=NonCallableMock(spec_set=[ - "annotate_context_with_state", + "compute_event_context", "get_current_state", ]), config=self.mock_config, @@ -110,7 +110,8 @@ class RoomMemberHandlerTestCase(unittest.TestCase): defer.succeed([]) ) - def annotate(_, ctx): + def annotate(_): + ctx = Mock() ctx.current_state = { (EventTypes.Member, "@alice:green"): self._create_member( user_id="@alice:green", @@ -121,10 +122,11 @@ class RoomMemberHandlerTestCase(unittest.TestCase): room_id=room_id, ), } + ctx.prev_state_events = [] - return defer.succeed(True) + return defer.succeed(ctx) - self.state_handler.annotate_context_with_state.side_effect = annotate + self.state_handler.compute_event_context.side_effect = annotate def add_auth(_, ctx): ctx.auth_events = ctx.current_state[ @@ -146,8 +148,8 @@ class RoomMemberHandlerTestCase(unittest.TestCase): yield room_handler.change_membership(event, context) - self.state_handler.annotate_context_with_state.assert_called_once_with( - builder, context + self.state_handler.compute_event_context.assert_called_once_with( + builder ) self.auth.add_auth_events.assert_called_once_with( @@ -189,7 +191,8 @@ class RoomMemberHandlerTestCase(unittest.TestCase): defer.succeed([]) ) - def annotate(_, ctx): + def annotate(_): + ctx = Mock() ctx.current_state = { (EventTypes.Member, "@bob:red"): self._create_member( user_id="@bob:red", @@ -197,10 +200,11 @@ class RoomMemberHandlerTestCase(unittest.TestCase): membership=Membership.INVITE ), } + ctx.prev_state_events = [] - return defer.succeed(True) + return defer.succeed(ctx) - self.state_handler.annotate_context_with_state.side_effect = annotate + self.state_handler.compute_event_context.side_effect = annotate def add_auth(_, ctx): ctx.auth_events = ctx.current_state[ @@ -262,7 +266,8 @@ class RoomMemberHandlerTestCase(unittest.TestCase): defer.succeed([]) ) - def annotate(_, ctx): + def annotate(_): + ctx = Mock() ctx.current_state = { (EventTypes.Member, "@bob:red"): self._create_member( user_id="@bob:red", @@ -270,10 +275,11 @@ class RoomMemberHandlerTestCase(unittest.TestCase): membership=Membership.JOIN ), } + ctx.prev_state_events = [] - return defer.succeed(True) + return defer.succeed(ctx) - self.state_handler.annotate_context_with_state.side_effect = annotate + self.state_handler.compute_event_context.side_effect = annotate def add_auth(_, ctx): ctx.auth_events = ctx.current_state[ diff --git a/tests/test_state.py b/tests/test_state.py index 197e35f140..98ad9e54cd 100644 --- a/tests/test_state.py +++ b/tests/test_state.py @@ -38,7 +38,6 @@ class StateTestCase(unittest.TestCase): @defer.inlineCallbacks def test_annotate_with_old_message(self): event = self.create_event(type="test_message", name="event") - context = Mock() old_state = [ self.create_event(type="test1", state_key="1"), @@ -46,8 +45,8 @@ class StateTestCase(unittest.TestCase): self.create_event(type="test2", state_key=""), ] - yield self.state.annotate_context_with_state( - event, context, old_state=old_state + context = yield self.state.compute_event_context( + event, old_state=old_state ) for k, v in context.current_state.items(): @@ -64,7 +63,6 @@ class StateTestCase(unittest.TestCase): @defer.inlineCallbacks def test_annotate_with_old_state(self): event = self.create_event(type="state", state_key="", name="event") - context = Mock() old_state = [ self.create_event(type="test1", state_key="1"), @@ -72,8 +70,8 @@ class StateTestCase(unittest.TestCase): self.create_event(type="test2", state_key=""), ] - yield self.state.annotate_context_with_state( - event, context, old_state=old_state + context = yield self.state.compute_event_context( + event, old_state=old_state ) for k, v in context.current_state.items(): @@ -92,7 +90,6 @@ class StateTestCase(unittest.TestCase): def test_trivial_annotate_message(self): event = self.create_event(type="test_message", name="event") event.prev_events = [] - context = Mock() old_state = [ self.create_event(type="test1", state_key="1"), @@ -106,7 +103,7 @@ class StateTestCase(unittest.TestCase): group_name: old_state, } - yield self.state.annotate_context_with_state(event, context) + context = yield self.state.compute_event_context(event) for k, v in context.current_state.items(): type, state_key = k @@ -124,7 +121,6 @@ class StateTestCase(unittest.TestCase): def test_trivial_annotate_state(self): event = self.create_event(type="state", state_key="", name="event") event.prev_events = [] - context = Mock() old_state = [ self.create_event(type="test1", state_key="1"), @@ -138,7 +134,7 @@ class StateTestCase(unittest.TestCase): group_name: old_state, } - yield self.state.annotate_context_with_state(event, context) + context = yield self.state.compute_event_context(event) for k, v in context.current_state.items(): type, state_key = k @@ -156,7 +152,6 @@ class StateTestCase(unittest.TestCase): def test_resolve_message_conflict(self): event = self.create_event(type="test_message", name="event") event.prev_events = [] - context = Mock() old_state_1 = [ self.create_event(type="test1", state_key="1"), @@ -178,7 +173,7 @@ class StateTestCase(unittest.TestCase): group_name_2: old_state_2, } - yield self.state.annotate_context_with_state(event, context) + context = yield self.state.compute_event_context(event) self.assertEqual(len(context.current_state), 5) @@ -188,7 +183,6 @@ class StateTestCase(unittest.TestCase): def test_resolve_state_conflict(self): event = self.create_event(type="test4", state_key="", name="event") event.prev_events = [] - context = Mock() old_state_1 = [ self.create_event(type="test1", state_key="1"), @@ -210,7 +204,7 @@ class StateTestCase(unittest.TestCase): group_name_2: old_state_2, } - yield self.state.annotate_context_with_state(event, context) + context = yield self.state.compute_event_context(event) self.assertEqual(len(context.current_state), 5) -- cgit 1.5.1