summary refs log tree commit diff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--tests/events/test_events.py55
-rw-r--r--tests/federation/test_federation.py237
-rw-r--r--tests/federation/test_pdu_codec.py160
-rw-r--r--tests/handlers/test_directory.py11
-rw-r--r--tests/handlers/test_federation.py93
-rw-r--r--tests/handlers/test_presence.py4
-rw-r--r--tests/handlers/test_presencelike.py6
-rw-r--r--tests/handlers/test_profile.py6
-rw-r--r--tests/handlers/test_room.py215
-rw-r--r--tests/handlers/test_typing.py4
-rw-r--r--tests/rest/test_events.py57
-rw-r--r--tests/rest/test_profile.py8
-rw-r--r--tests/rest/test_rooms.py267
-rw-r--r--tests/storage/test_base.py2
-rw-r--r--tests/storage/test_redaction.py16
-rw-r--r--tests/storage/test_room.py4
-rw-r--r--tests/storage/test_roommember.py26
-rw-r--r--tests/storage/test_stream.py41
-rw-r--r--tests/test_state.py693
-rw-r--r--tests/util/test_log_context.py43
-rw-r--r--tests/utils.py3
21 files changed, 748 insertions, 1203 deletions
diff --git a/tests/events/test_events.py b/tests/events/test_events.py
index a4b6cb3afd..91d1d44fee 100644
--- a/tests/events/test_events.py
+++ b/tests/events/test_events.py
@@ -14,6 +14,8 @@
 # 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
 
@@ -21,7 +23,7 @@ from tests import unittest
 class SynapseTemplateCheckTestCase(unittest.TestCase):
 
     def setUp(self):
-        pass
+        self.validator = EventValidator(None)
 
     def tearDown(self):
         pass
@@ -38,22 +40,28 @@ class SynapseTemplateCheckTestCase(unittest.TestCase):
         }
 
         event = MockSynapseEvent(template)
-        self.assertTrue(event.check_json(content, raises=False))
+        event.content = content
+        self.assertTrue(self.validator.validate(event))
 
         content = {
             "person": {"name": "bob"},
             "friends": ["jill"],
             "enemies": ["mike"]
         }
-        event = MockSynapseEvent(template)
-        self.assertTrue(event.check_json(content, raises=False))
+        event.content = content
+        self.assertTrue(self.validator.validate(event))
 
         content = {
             "person": {"name": "bob"},
             # missing friends
             "enemies": ["mike", "jill"]
         }
-        self.assertFalse(event.check_json(content, raises=False))
+        event.content = content
+        self.assertRaises(
+            SynapseError,
+            self.validator.validate,
+            event
+        )
 
     def test_lists(self):
         template = {
@@ -67,13 +75,19 @@ class SynapseTemplateCheckTestCase(unittest.TestCase):
         }
 
         event = MockSynapseEvent(template)
-        self.assertFalse(event.check_json(content, raises=False))
+        event.content = content
+        self.assertRaises(
+            SynapseError,
+            self.validator.validate,
+            event
+        )
 
         content = {
             "person": {"name": "bob"},
             "friends": [{"name": "jill"}, {"name": "mike"}]
         }
-        self.assertTrue(event.check_json(content, raises=False))
+        event.content = content
+        self.assertTrue(self.validator.validate(event))
 
     def test_nested_lists(self):
         template = {
@@ -103,7 +117,12 @@ class SynapseTemplateCheckTestCase(unittest.TestCase):
         }
 
         event = MockSynapseEvent(template)
-        self.assertFalse(event.check_json(content, raises=False))
+        event.content = content
+        self.assertRaises(
+            SynapseError,
+            self.validator.validate,
+            event
+        )
 
         content = {
             "results": {
@@ -117,7 +136,8 @@ class SynapseTemplateCheckTestCase(unittest.TestCase):
                 ]
             }
         }
-        self.assertTrue(event.check_json(content, raises=False))
+        event.content = content
+        self.assertTrue(self.validator.validate(event))
 
     def test_nested_keys(self):
         template = {
@@ -145,7 +165,8 @@ class SynapseTemplateCheckTestCase(unittest.TestCase):
             }
         }
 
-        self.assertTrue(event.check_json(content, raises=False))
+        event.content = content
+        self.assertTrue(self.validator.validate(event))
 
         content = {
             "person": {
@@ -159,7 +180,12 @@ class SynapseTemplateCheckTestCase(unittest.TestCase):
             }
         }
 
-        self.assertFalse(event.check_json(content, raises=False))
+        event.content = content
+        self.assertRaises(
+            SynapseError,
+            self.validator.validate,
+            event
+        )
 
         content = {
             "person": {
@@ -173,7 +199,12 @@ class SynapseTemplateCheckTestCase(unittest.TestCase):
             }
         }
 
-        self.assertFalse(event.check_json(content, raises=False))
+        event.content = content
+        self.assertRaises(
+            SynapseError,
+            self.validator.validate,
+            event
+        )
 
 
 class MockSynapseEvent(SynapseEvent):
diff --git a/tests/federation/test_federation.py b/tests/federation/test_federation.py
index 933aa61c77..efac4075dc 100644
--- a/tests/federation/test_federation.py
+++ b/tests/federation/test_federation.py
@@ -23,8 +23,7 @@ from ..utils import MockHttpResource, MockClock, MockKey
 
 from synapse.server import HomeServer
 from synapse.federation import initialize_http_replication
-from synapse.federation.units import Pdu
-from synapse.storage.pdu import PduTuple, PduEntry
+from synapse.api.events import SynapseEvent
 
 
 def make_pdu(prev_pdus=[], **kwargs):
@@ -41,7 +40,7 @@ def make_pdu(prev_pdus=[], **kwargs):
     }
     pdu_fields.update(kwargs)
 
-    return PduTuple(PduEntry(**pdu_fields), prev_pdus)
+    return SynapseEvent(prev_pdus=prev_pdus, **pdu_fields)
 
 
 class FederationTestCase(unittest.TestCase):
@@ -52,177 +51,182 @@ class FederationTestCase(unittest.TestCase):
             "put_json",
         ])
         self.mock_persistence = Mock(spec=[
-            "get_current_state_for_context",
-            "get_pdu",
-            "persist_event",
-            "update_min_depth_for_context",
             "prep_send_transaction",
             "delivered_txn",
             "get_received_txn_response",
             "set_received_txn_response",
         ])
         self.mock_persistence.get_received_txn_response.return_value = (
-                defer.succeed(None)
+            defer.succeed(None)
         )
         self.mock_config = Mock()
         self.mock_config.signing_key = [MockKey()]
         self.clock = MockClock()
-        hs = HomeServer("test",
-                resource_for_federation=self.mock_resource,
-                http_client=self.mock_http_client,
-                db_pool=None,
-                datastore=self.mock_persistence,
-                clock=self.clock,
-                config=self.mock_config,
-                keyring=Mock(),
+        hs = HomeServer(
+            "test",
+            resource_for_federation=self.mock_resource,
+            http_client=self.mock_http_client,
+            db_pool=None,
+            datastore=self.mock_persistence,
+            clock=self.clock,
+            config=self.mock_config,
+            keyring=Mock(),
         )
         self.federation = initialize_http_replication(hs)
         self.distributor = hs.get_distributor()
 
     @defer.inlineCallbacks
     def test_get_state(self):
-        self.mock_persistence.get_current_state_for_context.return_value = (
-            defer.succeed([])
-        )
+        mock_handler = Mock(spec=[
+            "get_state_for_pdu",
+        ])
+
+        self.federation.set_handler(mock_handler)
+
+        mock_handler.get_state_for_pdu.return_value = defer.succeed([])
 
         # Empty context initially
-        (code, response) = yield self.mock_resource.trigger("GET",
-                "/_matrix/federation/v1/state/my-context/", None)
+        (code, response) = yield self.mock_resource.trigger(
+            "GET",
+            "/_matrix/federation/v1/state/my-context/",
+            None
+        )
         self.assertEquals(200, code)
         self.assertFalse(response["pdus"])
 
         # Now lets give the context some state
-        self.mock_persistence.get_current_state_for_context.return_value = (
+        mock_handler.get_state_for_pdu.return_value = (
             defer.succeed([
                 make_pdu(
-                    pdu_id="the-pdu-id",
+                    event_id="the-pdu-id",
                     origin="red",
-                    context="my-context",
-                    pdu_type="m.topic",
-                    ts=123456789000,
+                    room_id="my-context",
+                    type="m.topic",
+                    origin_server_ts=123456789000,
                     depth=1,
-                    is_state=True,
-                    content_json='{"topic":"The topic"}',
+                    content={"topic": "The topic"},
                     state_key="",
                     power_level=1000,
-                    prev_state_id="last-pdu-id",
-                    prev_state_origin="blue",
+                    prev_state="last-pdu-id",
                 ),
             ])
         )
 
-        (code, response) = yield self.mock_resource.trigger("GET",
-                "/_matrix/federation/v1/state/my-context/", None)
+        (code, response) = yield self.mock_resource.trigger(
+            "GET",
+            "/_matrix/federation/v1/state/my-context/",
+            None
+        )
         self.assertEquals(200, code)
         self.assertEquals(1, len(response["pdus"]))
 
     @defer.inlineCallbacks
     def test_get_pdu(self):
-        self.mock_persistence.get_pdu.return_value = (
+        mock_handler = Mock(spec=[
+            "get_persisted_pdu",
+        ])
+
+        self.federation.set_handler(mock_handler)
+
+        mock_handler.get_persisted_pdu.return_value = (
             defer.succeed(None)
         )
 
-        (code, response) = yield self.mock_resource.trigger("GET",
-                "/_matrix/federation/v1/pdu/red/abc123def456/", None)
+        (code, response) = yield self.mock_resource.trigger(
+            "GET",
+            "/_matrix/federation/v1/event/abc123def456/",
+            None
+        )
         self.assertEquals(404, code)
 
         # Now insert such a PDU
-        self.mock_persistence.get_pdu.return_value = (
+        mock_handler.get_persisted_pdu.return_value = (
             defer.succeed(
                 make_pdu(
-                    pdu_id="abc123def456",
+                    event_id="abc123def456",
                     origin="red",
-                    context="my-context",
-                    pdu_type="m.text",
-                    ts=123456789001,
+                    room_id="my-context",
+                    type="m.text",
+                    origin_server_ts=123456789001,
                     depth=1,
-                    content_json='{"text":"Here is the message"}',
+                    content={"text": "Here is the message"},
                 )
             )
         )
 
-        (code, response) = yield self.mock_resource.trigger("GET",
-                "/_matrix/federation/v1/pdu/red/abc123def456/", None)
+        (code, response) = yield self.mock_resource.trigger(
+            "GET",
+            "/_matrix/federation/v1/event/abc123def456/",
+            None
+        )
         self.assertEquals(200, code)
         self.assertEquals(1, len(response["pdus"]))
-        self.assertEquals("m.text", response["pdus"][0]["pdu_type"])
+        self.assertEquals("m.text", response["pdus"][0]["type"])
 
     @defer.inlineCallbacks
     def test_send_pdu(self):
         self.mock_http_client.put_json.return_value = defer.succeed(
-                (200, "OK")
+            (200, "OK")
         )
 
-        pdu = Pdu(
-                pdu_id="abc123def456",
-                origin="red",
-                destinations=["remote"],
-                context="my-context",
-                origin_server_ts=123456789002,
-                pdu_type="m.test",
-                content={"testing": "content here"},
-                depth=1,
+        pdu = SynapseEvent(
+            event_id="abc123def456",
+            origin="red",
+            room_id="my-context",
+            type="m.text",
+            origin_server_ts=123456789001,
+            depth=1,
+            content={"text": "Here is the message"},
+            destinations=["remote"],
         )
 
         yield self.federation.send_pdu(pdu)
 
         self.mock_http_client.put_json.assert_called_with(
-                "remote",
-                path="/_matrix/federation/v1/send/1000000/",
-                data={
-                    "origin_server_ts": 1000000,
-                    "origin": "test",
-                    "pdus": [
-                        {
-                            "origin": "red",
-                            "pdu_id": "abc123def456",
-                            "prev_pdus": [],
-                            "origin_server_ts": 123456789002,
-                            "context": "my-context",
-                            "pdu_type": "m.test",
-                            "is_state": False,
-                            "content": {"testing": "content here"},
-                            "depth": 1,
-                        },
-                    ]
-                },
-                json_data_callback=ANY,
+            "remote",
+            path="/_matrix/federation/v1/send/1000000/",
+            data={
+                "origin_server_ts": 1000000,
+                "origin": "test",
+                "pdus": [
+                    pdu.get_pdu_json(),
+                ],
+                'pdu_failures': [],
+            },
+            json_data_callback=ANY,
         )
 
     @defer.inlineCallbacks
     def test_send_edu(self):
         self.mock_http_client.put_json.return_value = defer.succeed(
-                (200, "OK")
+            (200, "OK")
         )
 
         yield self.federation.send_edu(
-                destination="remote",
-                edu_type="m.test",
-                content={"testing": "content here"},
+            destination="remote",
+            edu_type="m.test",
+            content={"testing": "content here"},
         )
 
         # MockClock ensures we can guess these timestamps
         self.mock_http_client.put_json.assert_called_with(
-                "remote",
-                path="/_matrix/federation/v1/send/1000000/",
-                data={
-                    "origin": "test",
-                    "origin_server_ts": 1000000,
-                    "pdus": [],
-                    "edus": [
-                        {
-                            # TODO: SYN-103: Remove "origin" and "destination"
-                            "origin": "test",
-                            "destination": "remote",
-                            "edu_type": "m.test",
-                            "content": {"testing": "content here"},
-                        }
-                    ],
-                },
-                json_data_callback=ANY,
+            "remote",
+            path="/_matrix/federation/v1/send/1000000/",
+            data={
+                "origin": "test",
+                "origin_server_ts": 1000000,
+                "pdus": [],
+                "edus": [
+                    {
+                        "edu_type": "m.test",
+                        "content": {"testing": "content here"},
+                    }
+                ],
+                'pdu_failures': [],
+            },
+            json_data_callback=ANY,
         )
 
-
     @defer.inlineCallbacks
     def test_recv_edu(self):
         recv_observer = Mock()
@@ -230,24 +234,26 @@ class FederationTestCase(unittest.TestCase):
 
         self.federation.register_edu_handler("m.test", recv_observer)
 
-        yield self.mock_resource.trigger("PUT",
-                "/_matrix/federation/v1/send/1001000/",
-                """{
-                    "origin": "remote",
-                    "origin_server_ts": 1001000,
-                    "pdus": [],
-                    "edus": [
-                        {
-                            "origin": "remote",
-                            "destination": "test",
-                            "edu_type": "m.test",
-                            "content": {"testing": "reply here"}
-                        }
-                    ]
-                }""")
+        yield self.mock_resource.trigger(
+            "PUT",
+            "/_matrix/federation/v1/send/1001000/",
+            """{
+                "origin": "remote",
+                "origin_server_ts": 1001000,
+                "pdus": [],
+                "edus": [
+                    {
+                        "origin": "remote",
+                        "destination": "test",
+                        "edu_type": "m.test",
+                        "content": {"testing": "reply here"}
+                    }
+                ]
+            }"""
+        )
 
         recv_observer.assert_called_with(
-                "remote", {"testing": "reply here"}
+            "remote", {"testing": "reply here"}
         )
 
     @defer.inlineCallbacks
@@ -278,8 +284,11 @@ class FederationTestCase(unittest.TestCase):
 
         self.federation.register_query_handler("a-question", recv_handler)
 
-        code, response = yield self.mock_resource.trigger("GET",
-            "/_matrix/federation/v1/query/a-question?three=3&four=4", None)
+        code, response = yield self.mock_resource.trigger(
+            "GET",
+            "/_matrix/federation/v1/query/a-question?three=3&four=4",
+            None
+        )
 
         self.assertEquals(200, code)
         self.assertEquals({"another": "response"}, response)
diff --git a/tests/federation/test_pdu_codec.py b/tests/federation/test_pdu_codec.py
deleted file mode 100644
index 0754ef92e8..0000000000
--- a/tests/federation/test_pdu_codec.py
+++ /dev/null
@@ -1,160 +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 tests import unittest
-
-from synapse.federation.pdu_codec import (
-    PduCodec, encode_event_id, decode_event_id
-)
-from synapse.federation.units import Pdu
-#from synapse.api.events.room import MessageEvent
-
-from synapse.server import HomeServer
-
-from mock import Mock
-
-
-class PduCodecTestCase(unittest.TestCase):
-    def setUp(self):
-        self.hs = HomeServer("blargle.net")
-        self.event_factory = self.hs.get_event_factory()
-
-        self.codec = PduCodec(self.hs)
-
-    def test_decode_event_id(self):
-        self.assertEquals(
-            ("foo", "bar.com"),
-            decode_event_id("foo@bar.com", "A")
-        )
-
-        self.assertEquals(
-            ("foo", "bar.com"),
-            decode_event_id("foo", "bar.com")
-        )
-
-    def test_encode_event_id(self):
-        self.assertEquals("A@B", encode_event_id("A", "B"))
-
-    def test_codec_event_id(self):
-        event_id = "aa@bb.com"
-
-        self.assertEquals(
-            event_id,
-            encode_event_id(*decode_event_id(event_id, None))
-        )
-
-        pdu_id = ("aa", "bb.com")
-
-        self.assertEquals(
-            pdu_id,
-            decode_event_id(encode_event_id(*pdu_id), None)
-        )
-
-    def test_event_from_pdu(self):
-        pdu = Pdu(
-            pdu_id="foo",
-            context="rooooom",
-            pdu_type="m.room.message",
-            origin="bar.com",
-            origin_server_ts=12345,
-            depth=5,
-            prev_pdus=[("alice", "bob.com")],
-            is_state=False,
-            content={"msgtype": u"test"},
-        )
-
-        event = self.codec.event_from_pdu(pdu)
-
-        self.assertEquals("foo@bar.com", event.event_id)
-        self.assertEquals(pdu.context, event.room_id)
-        self.assertEquals(pdu.is_state, event.is_state)
-        self.assertEquals(pdu.depth, event.depth)
-        self.assertEquals(["alice@bob.com"], event.prev_events)
-        self.assertEquals(pdu.content, event.content)
-
-    def test_pdu_from_event(self):
-        event = self.event_factory.create_event(
-            etype="m.room.message",
-            event_id="gargh_id",
-            room_id="rooom",
-            user_id="sender",
-            content={"msgtype": u"test"},
-        )
-
-        pdu = self.codec.pdu_from_event(event)
-
-        self.assertEquals(event.event_id, pdu.pdu_id)
-        self.assertEquals(self.hs.hostname, pdu.origin)
-        self.assertEquals(event.room_id, pdu.context)
-        self.assertEquals(event.content, pdu.content)
-        self.assertEquals(event.type, pdu.pdu_type)
-
-        event = self.event_factory.create_event(
-            etype="m.room.message",
-            event_id="gargh_id@bob.com",
-            room_id="rooom",
-            user_id="sender",
-            content={"msgtype": u"test"},
-        )
-
-        pdu = self.codec.pdu_from_event(event)
-
-        self.assertEquals("gargh_id", pdu.pdu_id)
-        self.assertEquals("bob.com", pdu.origin)
-        self.assertEquals(event.room_id, pdu.context)
-        self.assertEquals(event.content, pdu.content)
-        self.assertEquals(event.type, pdu.pdu_type)
-
-    def test_event_from_state_pdu(self):
-        pdu = Pdu(
-            pdu_id="foo",
-            context="rooooom",
-            pdu_type="m.room.topic",
-            origin="bar.com",
-            origin_server_ts=12345,
-            depth=5,
-            prev_pdus=[("alice", "bob.com")],
-            is_state=True,
-            content={"topic": u"test"},
-            state_key="",
-        )
-
-        event = self.codec.event_from_pdu(pdu)
-
-        self.assertEquals("foo@bar.com", event.event_id)
-        self.assertEquals(pdu.context, event.room_id)
-        self.assertEquals(pdu.is_state, event.is_state)
-        self.assertEquals(pdu.depth, event.depth)
-        self.assertEquals(["alice@bob.com"], event.prev_events)
-        self.assertEquals(pdu.content, event.content)
-        self.assertEquals(pdu.state_key, event.state_key)
-
-    def test_pdu_from_state_event(self):
-        event = self.event_factory.create_event(
-            etype="m.room.topic",
-            event_id="gargh_id",
-            room_id="rooom",
-            user_id="sender",
-            content={"topic": u"test"},
-        )
-
-        pdu = self.codec.pdu_from_event(event)
-
-        self.assertEquals(event.event_id, pdu.pdu_id)
-        self.assertEquals(self.hs.hostname, pdu.origin)
-        self.assertEquals(event.room_id, pdu.context)
-        self.assertEquals(event.content, pdu.content)
-        self.assertEquals(event.type, pdu.pdu_type)
-        self.assertEquals(event.state_key, pdu.state_key)
diff --git a/tests/handlers/test_directory.py b/tests/handlers/test_directory.py
index e10a49a8ac..8e164e4be0 100644
--- a/tests/handlers/test_directory.py
+++ b/tests/handlers/test_directory.py
@@ -21,9 +21,8 @@ from mock import Mock
 
 from synapse.server import HomeServer
 from synapse.handlers.directory import DirectoryHandler
-from synapse.storage.directory import RoomAliasMapping
 
-from tests.utils import SQLiteMemoryDbPool
+from tests.utils import SQLiteMemoryDbPool, MockKey
 
 
 class DirectoryHandlers(object):
@@ -41,6 +40,7 @@ class DirectoryTestCase(unittest.TestCase):
         ])
 
         self.query_handlers = {}
+
         def register_query_handler(query_type, handler):
             self.query_handlers[query_type] = handler
         self.mock_federation.register_query_handler = register_query_handler
@@ -48,11 +48,16 @@ class DirectoryTestCase(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,
             http_client=None,
             resource_for_federation=Mock(),
             replication_layer=self.mock_federation,
+            config=self.mock_config,
         )
         hs.handlers = DirectoryHandlers(hs)
 
diff --git a/tests/handlers/test_federation.py b/tests/handlers/test_federation.py
index 219b2c4c5e..e19b073817 100644
--- a/tests/handlers/test_federation.py
+++ b/tests/handlers/test_federation.py
@@ -17,16 +17,16 @@ from twisted.internet import defer
 from tests import unittest
 
 from synapse.api.events.room import (
-    InviteJoinEvent, MessageEvent, RoomMemberEvent
+    MessageEvent,
 )
-from synapse.api.constants import Membership
+
+from synapse.api.events import SynapseEvent
 from synapse.handlers.federation import FederationHandler
 from synapse.server import HomeServer
-from synapse.federation.units import Pdu
 
-from mock import NonCallableMock, ANY
+from mock import NonCallableMock, ANY, Mock
 
-from ..utils import get_mock_call_args, MockKey
+from ..utils import MockKey
 
 
 class FederationTestCase(unittest.TestCase):
@@ -36,6 +36,14 @@ class FederationTestCase(unittest.TestCase):
         self.mock_config = NonCallableMock()
         self.mock_config.signing_key = [MockKey()]
 
+        self.state_handler = NonCallableMock(spec_set=[
+            "annotate_event_with_state",
+        ])
+
+        self.auth = NonCallableMock(spec_set=[
+            "check",
+        ])
+
         self.hostname = "test"
         hs = HomeServer(
             self.hostname,
@@ -53,6 +61,9 @@ class FederationTestCase(unittest.TestCase):
                 "federation_handler",
             ]),
             config=self.mock_config,
+            auth=self.auth,
+            state_handler=self.state_handler,
+            keyring=Mock(),
         )
 
         self.datastore = hs.get_datastore()
@@ -64,75 +75,37 @@ class FederationTestCase(unittest.TestCase):
 
     @defer.inlineCallbacks
     def test_msg(self):
-        pdu = Pdu(
-            pdu_type=MessageEvent.TYPE,
-            context="foo",
+        pdu = SynapseEvent(
+            type=MessageEvent.TYPE,
+            room_id="foo",
             content={"msgtype": u"fooo"},
             origin_server_ts=0,
-            pdu_id="a",
+            event_id="$a:b",
             origin="b",
+            hashes={"sha256":"PvbCLWrTBxnBsSO7/cJ76072ySTCgI/XGadESRAe02M"},
         )
 
-        store_id = "ASD"
-        self.datastore.persist_event.return_value = defer.succeed(store_id)
+        self.datastore.persist_event.return_value = defer.succeed(None)
         self.datastore.get_room.return_value = defer.succeed(True)
 
+        self.state_handler.annotate_event_with_state.return_value = (
+            defer.succeed(False)
+        )
+
         yield self.handlers.federation_handler.on_receive_pdu(pdu, False)
 
         self.datastore.persist_event.assert_called_once_with(
             ANY, False, is_new_state=False
         )
-        self.notifier.on_new_room_event.assert_called_once_with(ANY, extra_users=[])
-
-    @defer.inlineCallbacks
-    def test_invite_join_target_this(self):
-        room_id = "foo"
-        user_id = "@bob:red"
-
-        pdu = Pdu(
-            pdu_type=InviteJoinEvent.TYPE,
-            user_id=user_id,
-            target_host=self.hostname,
-            context=room_id,
-            content={},
-            origin_server_ts=0,
-            pdu_id="a",
-            origin="b",
-        )
-
-        yield self.handlers.federation_handler.on_receive_pdu(pdu, False)
 
-        mem_handler = self.handlers.room_member_handler
-        self.assertEquals(1, mem_handler.change_membership.call_count)
-        call_args = get_mock_call_args(
-            lambda event, do_auth: None,
-            mem_handler.change_membership
+        self.state_handler.annotate_event_with_state.assert_called_once_with(
+            ANY,
+            old_state=None,
         )
-        self.assertEquals(False, call_args["do_auth"])
 
-        new_event = call_args["event"]
-        self.assertEquals(RoomMemberEvent.TYPE, new_event.type)
-        self.assertEquals(room_id, new_event.room_id)
-        self.assertEquals(user_id, new_event.state_key)
-        self.assertEquals(Membership.JOIN, new_event.membership)
+        self.auth.check.assert_called_once_with(ANY, raises=True)
 
-    @defer.inlineCallbacks
-    def test_invite_join_target_other(self):
-        room_id = "foo"
-        user_id = "@bob:red"
-
-        pdu = Pdu(
-            pdu_type=InviteJoinEvent.TYPE,
-            user_id=user_id,
-            state_key="@red:not%s" % self.hostname,
-            context=room_id,
-            content={},
-            origin_server_ts=0,
-            pdu_id="a",
-            origin="b",
+        self.notifier.on_new_room_event.assert_called_once_with(
+            ANY,
+            extra_users=[]
         )
-
-        yield self.handlers.federation_handler.on_receive_pdu(pdu, False)
-
-        mem_handler = self.handlers.room_member_handler
-        self.assertEquals(0, mem_handler.change_membership.call_count)
diff --git a/tests/handlers/test_presence.py b/tests/handlers/test_presence.py
index fdc2e8de4a..cdaf93429b 100644
--- a/tests/handlers/test_presence.py
+++ b/tests/handlers/test_presence.py
@@ -44,13 +44,11 @@ def _expect_edu(destination, edu_type, content, origin="test"):
         "pdus": [],
         "edus": [
             {
-                # TODO: SYN-103: Remove "origin" and "destination" keys.
-                "origin": origin,
-                "destination": destination,
                 "edu_type": edu_type,
                 "content": content,
             }
         ],
+        "pdu_failures": [],
     }
 
 def _make_edu_json(origin, edu_type, content):
diff --git a/tests/handlers/test_presencelike.py b/tests/handlers/test_presencelike.py
index 047752ad68..532ecf0f2c 100644
--- a/tests/handlers/test_presencelike.py
+++ b/tests/handlers/test_presencelike.py
@@ -21,7 +21,7 @@ from twisted.internet import defer
 
 from mock import Mock, call, ANY
 
-from ..utils import MockClock
+from ..utils import MockClock, MockKey
 
 from synapse.server import HomeServer
 from synapse.api.constants import PresenceState
@@ -57,6 +57,9 @@ class PresenceAndProfileHandlers(object):
 class PresenceProfilelikeDataTestCase(unittest.TestCase):
 
     def setUp(self):
+        self.mock_config = Mock()
+        self.mock_config.signing_key = [MockKey()]
+
         hs = HomeServer("test",
                 clock=MockClock(),
                 db_pool=None,
@@ -72,6 +75,7 @@ class PresenceProfilelikeDataTestCase(unittest.TestCase):
                 resource_for_federation=Mock(),
                 http_client=None,
                 replication_layer=MockReplication(),
+                config=self.mock_config,
             )
         hs.handlers = PresenceAndProfileHandlers(hs)
 
diff --git a/tests/handlers/test_profile.py b/tests/handlers/test_profile.py
index 5dc9b456e1..1660e7e928 100644
--- a/tests/handlers/test_profile.py
+++ b/tests/handlers/test_profile.py
@@ -24,7 +24,7 @@ from synapse.server import HomeServer
 from synapse.handlers.profile import ProfileHandler
 from synapse.api.constants import Membership
 
-from tests.utils import SQLiteMemoryDbPool
+from tests.utils import SQLiteMemoryDbPool, MockKey
 
 
 class ProfileHandlers(object):
@@ -49,12 +49,16 @@ class ProfileTestCase(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,
                 http_client=None,
                 handlers=None,
                 resource_for_federation=Mock(),
                 replication_layer=self.mock_federation,
+                config=self.mock_config,
             )
         hs.handlers = ProfileHandlers(hs)
 
diff --git a/tests/handlers/test_room.py b/tests/handlers/test_room.py
index c88d1c8840..cbe591ab90 100644
--- a/tests/handlers/test_room.py
+++ b/tests/handlers/test_room.py
@@ -18,7 +18,7 @@ from twisted.internet import defer
 from tests import unittest
 
 from synapse.api.events.room import (
-    InviteJoinEvent, RoomMemberEvent, RoomConfigEvent
+    RoomMemberEvent,
 )
 from synapse.api.constants import Membership
 from synapse.handlers.room import RoomMemberHandler, RoomCreationHandler
@@ -34,6 +34,7 @@ class RoomMemberHandlerTestCase(unittest.TestCase):
     def setUp(self):
         self.mock_config = NonCallableMock()
         self.mock_config.signing_key = [MockKey()]
+
         self.hostname = "red"
         hs = HomeServer(
             self.hostname,
@@ -43,7 +44,6 @@ class RoomMemberHandlerTestCase(unittest.TestCase):
             ]),
             datastore=NonCallableMock(spec_set=[
                 "persist_event",
-                "get_joined_hosts_for_room",
                 "get_room_member",
                 "get_room",
                 "store_room",
@@ -57,13 +57,21 @@ class RoomMemberHandlerTestCase(unittest.TestCase):
                 "profile_handler",
                 "federation_handler",
             ]),
-            auth=NonCallableMock(spec_set=["check"]),
-            state_handler=NonCallableMock(spec_set=["handle_new_event"]),
+            auth=NonCallableMock(spec_set=[
+                "check",
+                "add_auth_events",
+                "check_host_in_room",
+            ]),
+            state_handler=NonCallableMock(spec_set=[
+                "annotate_event_with_state",
+                "get_current_state",
+            ]),
             config=self.mock_config,
         )
 
         self.federation = NonCallableMock(spec_set=[
             "handle_new_event",
+            "send_invite",
             "get_state_for_room",
         ])
 
@@ -72,6 +80,7 @@ class RoomMemberHandlerTestCase(unittest.TestCase):
         self.notifier = hs.get_notifier()
         self.state_handler = hs.get_state_handler()
         self.distributor = hs.get_distributor()
+        self.auth = hs.get_auth()
         self.hs = hs
 
         self.handlers.federation_handler = self.federation
@@ -104,28 +113,34 @@ class RoomMemberHandlerTestCase(unittest.TestCase):
             content=content,
         )
 
-        joined = ["red", "green"]
-
-        self.state_handler.handle_new_event.return_value = defer.succeed(True)
-        self.datastore.get_joined_hosts_for_room.return_value = (
-            defer.succeed(joined)
-        )
+        self.auth.check_host_in_room.return_value = defer.succeed(True)
 
         store_id = "store_id_fooo"
         self.datastore.persist_event.return_value = defer.succeed(store_id)
 
+        self.datastore.get_room_member.return_value = defer.succeed(None)
+
+        event.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,
+            ),
+            (RoomMemberEvent.TYPE, target_user_id): event,
+        }
+
         # Actual invocation
         yield self.room_member_handler.change_membership(event)
 
-        self.state_handler.handle_new_event.assert_called_once_with(
-            event, self.snapshot,
-        )
         self.federation.handle_new_event.assert_called_once_with(
             event, self.snapshot,
         )
 
         self.assertEquals(
-            set(["blue", "red", "green"]),
+            set(["red", "green"]),
             set(event.destinations)
         )
 
@@ -144,27 +159,13 @@ class RoomMemberHandlerTestCase(unittest.TestCase):
         room_id = "!foo:red"
         user_id = "@bob:red"
         user = self.hs.parse_userid(user_id)
-        target_user_id = "@bob:red"
-        content = {"membership": Membership.JOIN}
 
-        event = self.hs.get_event_factory().create_event(
-            etype=RoomMemberEvent.TYPE,
+        event = self._create_member(
             user_id=user_id,
-            state_key=target_user_id,
             room_id=room_id,
-            membership=Membership.JOIN,
-            content=content,
         )
 
-        joined = ["red", "green"]
-
-        self.state_handler.handle_new_event.return_value = defer.succeed(True)
-
-        def get_joined(*args):
-            return defer.succeed(joined)
-
-        self.datastore.get_joined_hosts_for_room.side_effect = get_joined
-
+        self.auth.check_host_in_room.return_value = defer.succeed(True)
 
         store_id = "store_id_fooo"
         self.datastore.persist_event.return_value = defer.succeed(store_id)
@@ -178,12 +179,17 @@ class RoomMemberHandlerTestCase(unittest.TestCase):
         join_signal_observer = Mock()
         self.distributor.observe("user_joined_room", join_signal_observer)
 
+        event.state_events = {
+            (RoomMemberEvent.TYPE, "@alice:green"): self._create_member(
+                user_id="@alice:green",
+                room_id=room_id,
+            ),
+            (RoomMemberEvent.TYPE, user_id): event,
+        }
+
         # Actual invocation
         yield self.room_member_handler.change_membership(event)
 
-        self.state_handler.handle_new_event.assert_called_once_with(
-            event, self.snapshot
-        )
         self.federation.handle_new_event.assert_called_once_with(
             event, self.snapshot
         )
@@ -197,138 +203,32 @@ class RoomMemberHandlerTestCase(unittest.TestCase):
             event
         )
         self.notifier.on_new_room_event.assert_called_once_with(
-                event, extra_users=[user])
-
-        join_signal_observer.assert_called_with(
-                user=user, room_id=room_id)
-
-    @defer.inlineCallbacks
-    def STALE_test_invite_join(self):
-        room_id = "foo"
-        user_id = "@bob:red"
-        target_user_id = "@bob:red"
-        content = {"membership": Membership.JOIN}
-
-        event = self.hs.get_event_factory().create_event(
-            etype=RoomMemberEvent.TYPE,
-            user_id=user_id,
-            target_user_id=target_user_id,
-            room_id=room_id,
-            membership=Membership.JOIN,
-            content=content,
-        )
-
-        joined = ["red", "blue", "green"]
-
-        self.state_handler.handle_new_event.return_value = defer.succeed(True)
-        self.datastore.get_joined_hosts_for_room.return_value = (
-            defer.succeed(joined)
-        )
-
-        store_id = "store_id_fooo"
-        self.datastore.store_room_member.return_value = defer.succeed(store_id)
-        self.datastore.get_room.return_value = defer.succeed(None)
-
-        prev_state = NonCallableMock(name="prev_state")
-        prev_state.membership = Membership.INVITE
-        prev_state.sender = "@foo:blue"
-        self.datastore.get_room_member.return_value = defer.succeed(prev_state)
-
-        # Actual invocation
-        yield self.room_member_handler.change_membership(event)
-
-        self.datastore.get_room_member.assert_called_once_with(
-            target_user_id, room_id
-        )
-
-        self.assertTrue(self.federation.handle_new_event.called)
-        args = self.federation.handle_new_event.call_args[0]
-        invite_join_event = args[0]
-
-        self.assertTrue(InviteJoinEvent.TYPE, invite_join_event.TYPE)
-        self.assertTrue("blue", invite_join_event.target_host)
-        self.assertTrue(room_id, invite_join_event.room_id)
-        self.assertTrue(user_id, invite_join_event.user_id)
-        self.assertFalse(hasattr(invite_join_event, "state_key"))
-
-        self.assertEquals(
-            set(["blue"]),
-            set(invite_join_event.destinations)
+            event, extra_users=[user]
         )
 
-        self.federation.get_state_for_room.assert_called_once_with(
-            "blue", room_id
+        join_signal_observer.assert_called_with(
+            user=user, room_id=room_id
         )
 
-        self.assertFalse(self.datastore.store_room_member.called)
-
-        self.assertFalse(self.notifier.on_new_room_event.called)
-        self.assertFalse(self.state_handler.handle_new_event.called)
-
-    @defer.inlineCallbacks
-    def STALE_test_invite_join_public(self):
-        room_id = "#foo:blue"
-        user_id = "@bob:red"
-        target_user_id = "@bob:red"
-        content = {"membership": Membership.JOIN}
-
-        event = self.hs.get_event_factory().create_event(
+    def _create_member(self, user_id, room_id):
+        return self.hs.get_event_factory().create_event(
             etype=RoomMemberEvent.TYPE,
             user_id=user_id,
-            target_user_id=target_user_id,
+            state_key=user_id,
             room_id=room_id,
             membership=Membership.JOIN,
-            content=content,
+            content={"membership": Membership.JOIN},
         )
 
-        joined = ["red", "blue", "green"]
-
-        self.state_handler.handle_new_event.return_value = defer.succeed(True)
-        self.datastore.get_joined_hosts_for_room.return_value = (
-            defer.succeed(joined)
-        )
-
-        store_id = "store_id_fooo"
-        self.datastore.store_room_member.return_value = defer.succeed(store_id)
-        self.datastore.get_room.return_value = defer.succeed(None)
-
-        prev_state = NonCallableMock(name="prev_state")
-        prev_state.membership = Membership.INVITE
-        prev_state.sender = "@foo:blue"
-        self.datastore.get_room_member.return_value = defer.succeed(prev_state)
-
-        # Actual invocation
-        yield self.room_member_handler.change_membership(event)
-
-        self.assertTrue(self.federation.handle_new_event.called)
-        args = self.federation.handle_new_event.call_args[0]
-        invite_join_event = args[0]
-
-        self.assertTrue(InviteJoinEvent.TYPE, invite_join_event.TYPE)
-        self.assertTrue("blue", invite_join_event.target_host)
-        self.assertTrue("foo", invite_join_event.room_id)
-        self.assertTrue(user_id, invite_join_event.user_id)
-        self.assertFalse(hasattr(invite_join_event, "state_key"))
-
-        self.assertEquals(
-            set(["blue"]),
-            set(invite_join_event.destinations)
-        )
-
-        self.federation.get_state_for_room.assert_called_once_with(
-            "blue", "foo"
-        )
-
-        self.assertFalse(self.datastore.store_room_member.called)
-
-        self.assertFalse(self.notifier.on_new_room_event.called)
-        self.assertFalse(self.state_handler.handle_new_event.called)
-
 
 class RoomCreationTest(unittest.TestCase):
 
     def setUp(self):
         self.hostname = "red"
+
+        self.mock_config = NonCallableMock()
+        self.mock_config.signing_key = [MockKey()]
+
         hs = HomeServer(
             self.hostname,
             db_pool=None,
@@ -345,12 +245,14 @@ class RoomCreationTest(unittest.TestCase):
                 "room_member_handler",
                 "federation_handler",
             ]),
-            auth=NonCallableMock(spec_set=["check"]),
-            state_handler=NonCallableMock(spec_set=["handle_new_event"]),
+            auth=NonCallableMock(spec_set=["check", "add_auth_events"]),
+            state_handler=NonCallableMock(spec_set=[
+                "annotate_event_with_state",
+            ]),
             ratelimiter=NonCallableMock(spec_set=[
                 "send_message",
             ]),
-            config=NonCallableMock(),
+            config=self.mock_config,
         )
 
         self.federation = NonCallableMock(spec_set=[
@@ -373,6 +275,11 @@ class RoomCreationTest(unittest.TestCase):
         ])
         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
@@ -400,6 +307,6 @@ class RoomCreationTest(unittest.TestCase):
         self.assertEquals(user_id, join_event.user_id)
         self.assertEquals(user_id, join_event.state_key)
 
-        self.assertTrue(self.state_handler.handle_new_event.called)
+        self.assertTrue(self.state_handler.annotate_event_with_state.called)
 
         self.assertTrue(self.federation.handle_new_event.called)
diff --git a/tests/handlers/test_typing.py b/tests/handlers/test_typing.py
index f1d3b27f74..adb5148351 100644
--- a/tests/handlers/test_typing.py
+++ b/tests/handlers/test_typing.py
@@ -33,13 +33,11 @@ def _expect_edu(destination, edu_type, content, origin="test"):
         "pdus": [],
         "edus": [
             {
-                # TODO: SYN-103: Remove "origin" and "destination" keys.
-                "origin": origin,
-                "destination": destination,
                 "edu_type": edu_type,
                 "content": content,
             }
         ],
+        "pdu_failures": [],
     }
 
 
diff --git a/tests/rest/test_events.py b/tests/rest/test_events.py
index 79b371c04d..4a3234c332 100644
--- a/tests/rest/test_events.py
+++ b/tests/rest/test_events.py
@@ -25,10 +25,7 @@ import synapse.rest.room
 
 from synapse.server import HomeServer
 
-# python imports
-import json
-
-from ..utils import MockHttpResource, MemoryDataStore
+from ..utils import MockHttpResource, SQLiteMemoryDbPool, MockKey
 from .utils import RestTestCase
 
 from mock import Mock, NonCallableMock
@@ -49,7 +46,7 @@ class EventStreamPaginationApiTestCase(unittest.TestCase):
     def tearDown(self):
         pass
 
-    def test_long_poll(self):
+    def TODO_test_long_poll(self):
         # stream from 'end' key, send (self+other) message, expect message.
 
         # stream from 'END', send (self+other) message, expect message.
@@ -64,7 +61,7 @@ class EventStreamPaginationApiTestCase(unittest.TestCase):
 
         pass
 
-    def test_stream_forward(self):
+    def TODO_test_stream_forward(self):
         # stream from START, expect injected items
 
         # stream from 'start' key, expect same content
@@ -80,14 +77,14 @@ class EventStreamPaginationApiTestCase(unittest.TestCase):
         # returned as end key
         pass
 
-    def test_limits(self):
+    def TODO_test_limits(self):
         # stream from a key, expect limit_num items
 
         # stream from START, expect limit_num items
 
         pass
 
-    def test_range(self):
+    def TODO_test_range(self):
         # stream from key to key, expect X items
 
         # stream from key to END, expect X items
@@ -97,7 +94,7 @@ class EventStreamPaginationApiTestCase(unittest.TestCase):
         # stream from START to END, expect all items
         pass
 
-    def test_direction(self):
+    def TODO_test_direction(self):
         # stream from END to START and fwds, expect newest first
 
         # stream from END to START and bwds, expect oldest first
@@ -116,19 +113,20 @@ class EventStreamPermissionsTestCase(RestTestCase):
     def setUp(self):
         self.mock_resource = MockHttpResource(prefix=PATH_PREFIX)
 
-        state_handler = Mock(spec=["handle_new_event"])
-        state_handler.handle_new_event.return_value = True
-
         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()]
+
+        db_pool = SQLiteMemoryDbPool()
+        yield db_pool.prepare()
+
         hs = HomeServer(
             "test",
-            db_pool=None,
+            db_pool=db_pool,
             http_client=None,
             replication_layer=Mock(),
-            state_handler=state_handler,
-            datastore=MemoryDataStore(),
             persistence_service=persistence_service,
             clock=Mock(spec=[
                 "call_later",
@@ -139,7 +137,7 @@ class EventStreamPermissionsTestCase(RestTestCase):
             ratelimiter=NonCallableMock(spec_set=[
                 "send_message",
             ]),
-            config=NonCallableMock(),
+            config=self.mock_config,
         )
         self.ratelimiter = hs.get_ratelimiter()
         self.ratelimiter.send_message.return_value = (True, 0)
@@ -148,6 +146,7 @@ class EventStreamPermissionsTestCase(RestTestCase):
         hs.get_handlers().federation_handler = Mock()
 
         hs.get_clock().time_msec.return_value = 1000000
+        hs.get_clock().time.return_value = 1000
 
         synapse.rest.register.register_servlets(hs, self.mock_resource)
         synapse.rest.events.register_servlets(hs, self.mock_resource)
@@ -172,12 +171,14 @@ class EventStreamPermissionsTestCase(RestTestCase):
     def test_stream_basic_permissions(self):
         # invalid token, expect 403
         (code, response) = yield self.mock_resource.trigger_get(
-                           "/events?access_token=%s" % ("invalid" + self.token))
+            "/events?access_token=%s" % ("invalid" + self.token, )
+        )
         self.assertEquals(403, code, msg=str(response))
 
         # valid token, expect content
         (code, response) = yield self.mock_resource.trigger_get(
-                           "/events?access_token=%s&timeout=0" % (self.token))
+            "/events?access_token=%s&timeout=0" % (self.token,)
+        )
         self.assertEquals(200, code, msg=str(response))
         self.assertTrue("chunk" in response)
         self.assertTrue("start" in response)
@@ -185,15 +186,23 @@ class EventStreamPermissionsTestCase(RestTestCase):
 
     @defer.inlineCallbacks
     def test_stream_room_permissions(self):
-        room_id = yield self.create_room_as(self.other_user,
-                                            tok=self.other_token)
+        room_id = yield self.create_room_as(
+            self.other_user,
+            tok=self.other_token
+        )
         yield self.send(room_id, tok=self.other_token)
 
         # invited to room (expect no content for room)
-        yield self.invite(room_id, src=self.other_user, targ=self.user_id,
-                          tok=self.other_token)
+        yield self.invite(
+            room_id,
+            src=self.other_user,
+            targ=self.user_id,
+            tok=self.other_token
+        )
+
         (code, response) = yield self.mock_resource.trigger_get(
-                           "/events?access_token=%s&timeout=0" % (self.token))
+            "/events?access_token=%s&timeout=0" % (self.token,)
+        )
         self.assertEquals(200, code, msg=str(response))
 
         self.assertEquals(0, len(response["chunk"]))
@@ -203,7 +212,7 @@ class EventStreamPermissionsTestCase(RestTestCase):
 
         # left to room (expect no content for room)
 
-    def test_stream_items(self):
+    def TODO_test_stream_items(self):
         # new user, no content
 
         # join room, expect 1 item (join)
diff --git a/tests/rest/test_profile.py b/tests/rest/test_profile.py
index b0f48e7fd8..3a0d1e700a 100644
--- a/tests/rest/test_profile.py
+++ b/tests/rest/test_profile.py
@@ -18,9 +18,9 @@
 from tests import unittest
 from twisted.internet import defer
 
-from mock import Mock
+from mock import Mock, NonCallableMock
 
-from ..utils import MockHttpResource
+from ..utils import MockHttpResource, MockKey
 
 from synapse.api.errors import SynapseError, AuthError
 from synapse.server import HomeServer
@@ -41,6 +41,9 @@ class ProfileTestCase(unittest.TestCase):
             "set_avatar_url",
         ])
 
+        self.mock_config = NonCallableMock()
+        self.mock_config.signing_key = [MockKey()]
+
         hs = HomeServer("test",
             db_pool=None,
             http_client=None,
@@ -48,6 +51,7 @@ class ProfileTestCase(unittest.TestCase):
             federation=Mock(),
             replication_layer=Mock(),
             datastore=None,
+            config=self.mock_config,
         )
 
         def _get_user_by_req(request=None):
diff --git a/tests/rest/test_rooms.py b/tests/rest/test_rooms.py
index 29f5776f49..98c6af97b0 100644
--- a/tests/rest/test_rooms.py
+++ b/tests/rest/test_rooms.py
@@ -23,11 +23,14 @@ from synapse.api.constants import Membership
 
 from synapse.server import HomeServer
 
+from tests import unittest
+
 # python imports
 import json
 import urllib
+import types
 
-from ..utils import MockHttpResource, MemoryDataStore
+from ..utils import MockHttpResource, SQLiteMemoryDbPool, MockKey
 from .utils import RestTestCase
 
 from mock import Mock, NonCallableMock
@@ -44,24 +47,21 @@ class RoomPermissionsTestCase(RestTestCase):
     def setUp(self):
         self.mock_resource = MockHttpResource(prefix=PATH_PREFIX)
 
-        state_handler = Mock(spec=["handle_new_event"])
-        state_handler.handle_new_event.return_value = True
+        self.mock_config = NonCallableMock()
+        self.mock_config.signing_key = [MockKey()]
 
-        persistence_service = Mock(spec=["get_latest_pdus_in_context"])
-        persistence_service.get_latest_pdus_in_context.return_value = []
+        db_pool = SQLiteMemoryDbPool()
+        yield db_pool.prepare()
 
         hs = HomeServer(
             "red",
-            db_pool=None,
+            db_pool=db_pool,
             http_client=None,
-            datastore=MemoryDataStore(),
             replication_layer=Mock(),
-            state_handler=state_handler,
-            persistence_service=persistence_service,
             ratelimiter=NonCallableMock(spec_set=[
                 "send_message",
             ]),
-            config=NonCallableMock(),
+            config=self.mock_config,
         )
         self.ratelimiter = hs.get_ratelimiter()
         self.ratelimiter.send_message.return_value = (True, 0)
@@ -76,6 +76,10 @@ class RoomPermissionsTestCase(RestTestCase):
             }
         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
+
         self.auth_user_id = self.rmcreator_id
 
         synapse.rest.room.register_servlets(hs, self.mock_resource)
@@ -147,38 +151,55 @@ class RoomPermissionsTestCase(RestTestCase):
     @defer.inlineCallbacks
     def test_send_message(self):
         msg_content = '{"msgtype":"m.text","body":"hello"}'
-        send_msg_path = ("/rooms/%s/send/m.room.message/mid1" %
-                        (self.created_rmid))
+        send_msg_path = (
+            "/rooms/%s/send/m.room.message/mid1" % (self.created_rmid,)
+        )
 
         # send message in uncreated room, expect 403
         (code, response) = yield self.mock_resource.trigger(
-                           "PUT",
-                           "/rooms/%s/send/m.room.message/mid2" %
-                           (self.uncreated_rmid), msg_content)
+            "PUT",
+            "/rooms/%s/send/m.room.message/mid2" % (self.uncreated_rmid,),
+            msg_content
+        )
         self.assertEquals(403, code, msg=str(response))
 
         # send message in created room not joined (no state), expect 403
         (code, response) = yield self.mock_resource.trigger(
-                           "PUT", send_msg_path, msg_content)
+            "PUT",
+            send_msg_path,
+            msg_content
+        )
         self.assertEquals(403, code, msg=str(response))
 
         # send message in created room and invited, expect 403
-        yield self.invite(room=self.created_rmid, src=self.rmcreator_id,
-                          targ=self.user_id)
+        yield self.invite(
+            room=self.created_rmid,
+            src=self.rmcreator_id,
+            targ=self.user_id
+        )
         (code, response) = yield self.mock_resource.trigger(
-                           "PUT", send_msg_path, msg_content)
+            "PUT",
+            send_msg_path,
+            msg_content
+        )
         self.assertEquals(403, code, msg=str(response))
 
         # send message in created room and joined, expect 200
         yield self.join(room=self.created_rmid, user=self.user_id)
         (code, response) = yield self.mock_resource.trigger(
-                           "PUT", send_msg_path, msg_content)
+            "PUT",
+            send_msg_path,
+            msg_content
+        )
         self.assertEquals(200, code, msg=str(response))
 
         # send message in created room and left, expect 403
         yield self.leave(room=self.created_rmid, user=self.user_id)
         (code, response) = yield self.mock_resource.trigger(
-                           "PUT", send_msg_path, msg_content)
+            "PUT",
+            send_msg_path,
+            msg_content
+        )
         self.assertEquals(403, code, msg=str(response))
 
     @defer.inlineCallbacks
@@ -209,15 +230,20 @@ class RoomPermissionsTestCase(RestTestCase):
                            "PUT", topic_path, topic_content)
         self.assertEquals(403, code, msg=str(response))
 
-        # get topic in created PRIVATE room and invited, expect 200 (or 404)
+        # get topic in created PRIVATE room and invited, expect 403
         (code, response) = yield self.mock_resource.trigger_get(topic_path)
-        self.assertEquals(404, code, msg=str(response))
+        self.assertEquals(403, code, msg=str(response))
 
         # set/get topic in created PRIVATE room and joined, expect 200
         yield self.join(room=self.created_rmid, user=self.user_id)
+
+        # Only room ops can set topic by default
+        self.auth_user_id = self.rmcreator_id
         (code, response) = yield self.mock_resource.trigger(
                            "PUT", topic_path, topic_content)
         self.assertEquals(200, code, msg=str(response))
+        self.auth_user_id = self.user_id
+
         (code, response) = yield self.mock_resource.trigger_get(topic_path)
         self.assertEquals(200, code, msg=str(response))
         self.assert_dict(json.loads(topic_content), response)
@@ -230,10 +256,10 @@ class RoomPermissionsTestCase(RestTestCase):
         (code, response) = yield self.mock_resource.trigger_get(topic_path)
         self.assertEquals(403, code, msg=str(response))
 
-        # get topic in PUBLIC room, not joined, expect 200 (or 404)
+        # get topic in PUBLIC room, not joined, expect 403
         (code, response) = yield self.mock_resource.trigger_get(
                            "/rooms/%s/state/m.room.topic" % self.created_public_rmid)
-        self.assertEquals(200, code, msg=str(response))
+        self.assertEquals(403, code, msg=str(response))
 
         # set topic in PUBLIC room, not joined, expect 403
         (code, response) = yield self.mock_resource.trigger(
@@ -300,12 +326,12 @@ class RoomPermissionsTestCase(RestTestCase):
     def test_membership_public_room_perms(self):
         room = self.created_public_rmid
         # get membership of self, get membership of other, public room + invite
-        # expect all 200s - public rooms, you can see who is in them.
+        # expect 403
         yield self.invite(room=room, src=self.rmcreator_id,
                           targ=self.user_id)
         yield self._test_get_membership(
             members=[self.user_id, self.rmcreator_id],
-            room=room, expect_code=200)
+            room=room, expect_code=403)
 
         # get membership of self, get membership of other, public room + joined
         # expect all 200s
@@ -315,11 +341,11 @@ class RoomPermissionsTestCase(RestTestCase):
             room=room, expect_code=200)
 
         # get membership of self, get membership of other, public room + left
-        # expect all 200s - public rooms, you can always see who is in them.
+        # expect 403.
         yield self.leave(room=room, user=self.user_id)
         yield self._test_get_membership(
             members=[self.user_id, self.rmcreator_id],
-            room=room, expect_code=200)
+            room=room, expect_code=403)
 
     @defer.inlineCallbacks
     def test_invited_permissions(self):
@@ -381,45 +407,55 @@ class RoomPermissionsTestCase(RestTestCase):
         # set [invite/join/left] of self, set [invite/join/left] of other,
         # expect all 403s
         for usr in [self.user_id, self.rmcreator_id]:
-            yield self.change_membership(room=room, src=self.user_id,
-                                     targ=usr,
-                                     membership=Membership.INVITE,
-                                     expect_code=403)
-            yield self.change_membership(room=room, src=self.user_id,
-                                     targ=usr,
-                                     membership=Membership.JOIN,
-                                     expect_code=403)
-            yield self.change_membership(room=room, src=self.user_id,
-                                     targ=usr,
-                                     membership=Membership.LEAVE,
-                                     expect_code=403)
+            yield self.change_membership(
+                room=room,
+                src=self.user_id,
+                targ=usr,
+                membership=Membership.INVITE,
+                expect_code=403
+            )
+
+            yield self.change_membership(
+                room=room,
+                src=self.user_id,
+                targ=usr,
+                membership=Membership.JOIN,
+                expect_code=403
+            )
+
+        # It is always valid to LEAVE if you've already left (currently.)
+        yield self.change_membership(
+            room=room,
+            src=self.user_id,
+            targ=self.rmcreator_id,
+            membership=Membership.LEAVE,
+            expect_code=403
+        )
 
 
 class RoomsMemberListTestCase(RestTestCase):
     """ Tests /rooms/$room_id/members/list REST events."""
     user_id = "@sid1:red"
 
+    @defer.inlineCallbacks
     def setUp(self):
         self.mock_resource = MockHttpResource(prefix=PATH_PREFIX)
 
-        state_handler = Mock(spec=["handle_new_event"])
-        state_handler.handle_new_event.return_value = True
+        self.mock_config = NonCallableMock()
+        self.mock_config.signing_key = [MockKey()]
 
-        persistence_service = Mock(spec=["get_latest_pdus_in_context"])
-        persistence_service.get_latest_pdus_in_context.return_value = []
+        db_pool = SQLiteMemoryDbPool()
+        yield db_pool.prepare()
 
         hs = HomeServer(
             "red",
-            db_pool=None,
+            db_pool=db_pool,
             http_client=None,
-            datastore=MemoryDataStore(),
             replication_layer=Mock(),
-            state_handler=state_handler,
-            persistence_service=persistence_service,
             ratelimiter=NonCallableMock(spec_set=[
                 "send_message",
             ]),
-            config=NonCallableMock(),
+            config=self.mock_config,
         )
         self.ratelimiter = hs.get_ratelimiter()
         self.ratelimiter.send_message.return_value = (True, 0)
@@ -436,6 +472,10 @@ class RoomsMemberListTestCase(RestTestCase):
             }
         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)
 
     def tearDown(self):
@@ -487,28 +527,26 @@ class RoomsCreateTestCase(RestTestCase):
     """ Tests /rooms and /rooms/$room_id REST events. """
     user_id = "@sid1:red"
 
+    @defer.inlineCallbacks
     def setUp(self):
         self.mock_resource = MockHttpResource(prefix=PATH_PREFIX)
         self.auth_user_id = self.user_id
 
-        state_handler = Mock(spec=["handle_new_event"])
-        state_handler.handle_new_event.return_value = True
+        self.mock_config = NonCallableMock()
+        self.mock_config.signing_key = [MockKey()]
 
-        persistence_service = Mock(spec=["get_latest_pdus_in_context"])
-        persistence_service.get_latest_pdus_in_context.return_value = []
+        db_pool = SQLiteMemoryDbPool()
+        yield db_pool.prepare()
 
         hs = HomeServer(
             "red",
-            db_pool=None,
+            db_pool=db_pool,
             http_client=None,
-            datastore=MemoryDataStore(),
             replication_layer=Mock(),
-            state_handler=state_handler,
-            persistence_service=persistence_service,
             ratelimiter=NonCallableMock(spec_set=[
                 "send_message",
             ]),
-            config=NonCallableMock(),
+            config=self.mock_config,
         )
         self.ratelimiter = hs.get_ratelimiter()
         self.ratelimiter.send_message.return_value = (True, 0)
@@ -523,6 +561,10 @@ class RoomsCreateTestCase(RestTestCase):
             }
         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)
 
     def tearDown(self):
@@ -592,24 +634,21 @@ class RoomTopicTestCase(RestTestCase):
         self.mock_resource = MockHttpResource(prefix=PATH_PREFIX)
         self.auth_user_id = self.user_id
 
-        state_handler = Mock(spec=["handle_new_event"])
-        state_handler.handle_new_event.return_value = True
+        self.mock_config = NonCallableMock()
+        self.mock_config.signing_key = [MockKey()]
 
-        persistence_service = Mock(spec=["get_latest_pdus_in_context"])
-        persistence_service.get_latest_pdus_in_context.return_value = []
+        db_pool = SQLiteMemoryDbPool()
+        yield db_pool.prepare()
 
         hs = HomeServer(
             "red",
-            db_pool=None,
+            db_pool=db_pool,
             http_client=None,
-            datastore=MemoryDataStore(),
             replication_layer=Mock(),
-            state_handler=state_handler,
-            persistence_service=persistence_service,
             ratelimiter=NonCallableMock(spec_set=[
                 "send_message",
             ]),
-            config=NonCallableMock(),
+            config=self.mock_config,
         )
         self.ratelimiter = hs.get_ratelimiter()
         self.ratelimiter.send_message.return_value = (True, 0)
@@ -622,13 +661,18 @@ class RoomTopicTestCase(RestTestCase):
                 "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)
 
         # create the room
         self.room_id = yield self.create_room_as(self.user_id)
-        self.path = "/rooms/%s/state/m.room.topic" % self.room_id
+        self.path = "/rooms/%s/state/m.room.topic" % (self.room_id,)
 
     def tearDown(self):
         pass
@@ -706,24 +750,21 @@ class RoomMemberStateTestCase(RestTestCase):
         self.mock_resource = MockHttpResource(prefix=PATH_PREFIX)
         self.auth_user_id = self.user_id
 
-        state_handler = Mock(spec=["handle_new_event"])
-        state_handler.handle_new_event.return_value = True
+        self.mock_config = NonCallableMock()
+        self.mock_config.signing_key = [MockKey()]
 
-        persistence_service = Mock(spec=["get_latest_pdus_in_context"])
-        persistence_service.get_latest_pdus_in_context.return_value = []
+        db_pool = SQLiteMemoryDbPool()
+        yield db_pool.prepare()
 
         hs = HomeServer(
             "red",
-            db_pool=None,
+            db_pool=db_pool,
             http_client=None,
-            datastore=MemoryDataStore(),
             replication_layer=Mock(),
-            state_handler=state_handler,
-            persistence_service=persistence_service,
             ratelimiter=NonCallableMock(spec_set=[
                 "send_message",
             ]),
-            config=NonCallableMock(),
+            config=self.mock_config,
         )
         self.ratelimiter = hs.get_ratelimiter()
         self.ratelimiter.send_message.return_value = (True, 0)
@@ -736,13 +777,12 @@ class RoomMemberStateTestCase(RestTestCase):
                 "admin": False,
                 "device_id": 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)
@@ -847,24 +887,21 @@ class RoomMessagesTestCase(RestTestCase):
         self.mock_resource = MockHttpResource(prefix=PATH_PREFIX)
         self.auth_user_id = self.user_id
 
-        state_handler = Mock(spec=["handle_new_event"])
-        state_handler.handle_new_event.return_value = True
+        self.mock_config = NonCallableMock()
+        self.mock_config.signing_key = [MockKey()]
 
-        persistence_service = Mock(spec=["get_latest_pdus_in_context"])
-        persistence_service.get_latest_pdus_in_context.return_value = []
+        db_pool = SQLiteMemoryDbPool()
+        yield db_pool.prepare()
 
         hs = HomeServer(
             "red",
-            db_pool=None,
+            db_pool=db_pool,
             http_client=None,
-            datastore=MemoryDataStore(),
             replication_layer=Mock(),
-            state_handler=state_handler,
-            persistence_service=persistence_service,
             ratelimiter=NonCallableMock(spec_set=[
                 "send_message",
             ]),
-            config=NonCallableMock(),
+            config=self.mock_config,
         )
         self.ratelimiter = hs.get_ratelimiter()
         self.ratelimiter.send_message.return_value = (True, 0)
@@ -879,6 +916,10 @@ class RoomMessagesTestCase(RestTestCase):
             }
         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)
@@ -950,24 +991,21 @@ class RoomInitialSyncTestCase(RestTestCase):
         self.mock_resource = MockHttpResource(prefix=PATH_PREFIX)
         self.auth_user_id = self.user_id
 
-        state_handler = Mock(spec=["handle_new_event"])
-        state_handler.handle_new_event.return_value = True
+        self.mock_config = NonCallableMock()
+        self.mock_config.signing_key = [MockKey()]
 
-        persistence_service = Mock(spec=["get_latest_pdus_in_context"])
-        persistence_service.get_latest_pdus_in_context.return_value = []
+        db_pool = SQLiteMemoryDbPool()
+        yield db_pool.prepare()
 
         hs = HomeServer(
             "red",
-            db_pool=None,
+            db_pool=db_pool,
             http_client=None,
-            datastore=MemoryDataStore(),
             replication_layer=Mock(),
-            state_handler=state_handler,
-            persistence_service=persistence_service,
             ratelimiter=NonCallableMock(spec_set=[
                 "send_message",
             ]),
-            config=NonCallableMock(),
+            config=self.mock_config,
         )
         self.ratelimiter = hs.get_ratelimiter()
         self.ratelimiter.send_message.return_value = (True, 0)
@@ -982,30 +1020,11 @@ class RoomInitialSyncTestCase(RestTestCase):
             }
         hs.get_auth().get_user_by_token = _get_user_by_token
 
-        synapse.rest.room.register_servlets(hs, self.mock_resource)
+        def _insert_client_ip(*args, **kwargs):
+            return defer.succeed(None)
+        hs.get_datastore().insert_client_ip = _insert_client_ip
 
-        # MemoryDataStore's get_current_state() isn't even approximately
-        # right. Longterm we'll be killing it in favour of a real
-        # SQLite :memory:-based test. For now lets patch it
-        efact = hs.get_event_factory()
-        def get_current_state(room_id):
-            """
-            TODO: these probably need content
-            ('!WxMBxqtWbMMdMEkRqY:red', 'm.room.send_event_level', ''),
-            ('!WxMBxqtWbMMdMEkRqY:red', 'm.room.power_levels', ''),
-            ('!WxMBxqtWbMMdMEkRqY:red', 'm.room.ops_levels', ''),
-            ('!WxMBxqtWbMMdMEkRqY:red', 'm.room.member', '@sid1:red'),
-            ('!WxMBxqtWbMMdMEkRqY:red', 'm.room.add_state_level', '')]
-            """
-            return [
-                efact.create_event(etype="m.room.create", room_id=room_id,
-                    content={},
-                ),
-                efact.create_event(etype="m.room.join_rules", room_id=room_id,
-                    content={},
-                ),
-            ]
-        hs.datastore.get_current_state = get_current_state
+        synapse.rest.room.register_servlets(hs, self.mock_resource)
 
         # create the room
         self.room_id = yield self.create_room_as(self.user_id)
diff --git a/tests/storage/test_base.py b/tests/storage/test_base.py
index 3ad9a4b0c0..fabd364be9 100644
--- a/tests/storage/test_base.py
+++ b/tests/storage/test_base.py
@@ -74,7 +74,7 @@ class SQLBaseStoreTestCase(unittest.TestCase):
     @defer.inlineCallbacks
     def test_select_one_1col(self):
         self.mock_txn.rowcount = 1
-        self.mock_txn.fetchone.return_value = ("Value",)
+        self.mock_txn.fetchall.return_value = [("Value",)]
 
         value = yield self.datastore._simple_select_one_onecol(
                 table="tablename",
diff --git a/tests/storage/test_redaction.py b/tests/storage/test_redaction.py
index dae1641ea1..adfe64a980 100644
--- a/tests/storage/test_redaction.py
+++ b/tests/storage/test_redaction.py
@@ -61,6 +61,7 @@ class RedactionTestCase(unittest.TestCase):
             membership=membership,
             content={"membership": membership},
             depth=self.depth,
+            prev_events=[],
         )
 
         event.content.update(extra_content)
@@ -68,6 +69,11 @@ class RedactionTestCase(unittest.TestCase):
         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
@@ -85,8 +91,13 @@ class RedactionTestCase(unittest.TestCase):
             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 = []
+
         yield self.store.persist_event(
             event
         )
@@ -102,8 +113,13 @@ class RedactionTestCase(unittest.TestCase):
             content={"reason": reason},
             depth=self.depth,
             redacts=event_id,
+            prev_events=[],
         )
 
+        event.state_events = None
+        event.hashes = {}
+        event.auth_events = []
+
         yield self.store.persist_event(
             event
         )
diff --git a/tests/storage/test_room.py b/tests/storage/test_room.py
index 369a73d917..4ff02c306b 100644
--- a/tests/storage/test_room.py
+++ b/tests/storage/test_room.py
@@ -127,7 +127,7 @@ class RoomEventsStoreTestCase(unittest.TestCase):
         )
 
     @defer.inlineCallbacks
-    def test_room_name(self):
+    def STALE_test_room_name(self):
         name = u"A-Room-Name"
 
         yield self.inject_room_event(
@@ -150,7 +150,7 @@ class RoomEventsStoreTestCase(unittest.TestCase):
         )
 
     @defer.inlineCallbacks
-    def test_room_name(self):
+    def STALE_test_room_topic(self):
         topic = u"A place for things"
 
         yield self.inject_room_event(
diff --git a/tests/storage/test_roommember.py b/tests/storage/test_roommember.py
index eae278ee8d..8614e5ca9d 100644
--- a/tests/storage/test_roommember.py
+++ b/tests/storage/test_roommember.py
@@ -51,16 +51,24 @@ class RoomMemberStoreTestCase(unittest.TestCase):
     @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=[],
+        )
+
+        event.state_events = None
+        event.hashes = {}
+        event.prev_state = {}
+        event.auth_events = {}
+
         yield self.store.persist_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,
-            )
+            event
         )
 
     @defer.inlineCallbacks
diff --git a/tests/storage/test_stream.py b/tests/storage/test_stream.py
index ab30e6ea25..5038546aee 100644
--- a/tests/storage/test_stream.py
+++ b/tests/storage/test_stream.py
@@ -48,7 +48,7 @@ class StreamStoreTestCase(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):
         self.depth += 1
 
         event = self.event_factory.create_event(
@@ -59,10 +59,17 @@ class StreamStoreTestCase(unittest.TestCase):
             membership=membership,
             content={"membership": membership},
             depth=self.depth,
+            prev_events=[],
         )
 
-        if prev_state:
-            event.prev_state = prev_state
+        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
 
         # Have to create a join event using the eventfactory
         yield self.store.persist_event(
@@ -75,15 +82,22 @@ class StreamStoreTestCase(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 = []
+
         # Have to create a join event using the eventfactory
         yield self.store.persist_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,
-            )
+            event
         )
 
     @defer.inlineCallbacks
@@ -206,7 +220,7 @@ class StreamStoreTestCase(unittest.TestCase):
 
         event2 = yield self.inject_room_member(
             self.room1, self.u_alice, Membership.JOIN,
-            prev_state=event1.event_id,
+            replaces_state=event1.event_id,
         )
 
         end = yield self.store.get_room_events_max_id()
@@ -223,4 +237,7 @@ class StreamStoreTestCase(unittest.TestCase):
 
         event = results[0]
 
-        self.assertTrue(hasattr(event, "prev_content"), msg="No prev_content key")
+        self.assertTrue(
+            hasattr(event, "prev_content"),
+            msg="No prev_content key"
+        )
diff --git a/tests/test_state.py b/tests/test_state.py
index 4b1feaf410..7979b54a35 100644
--- a/tests/test_state.py
+++ b/tests/test_state.py
@@ -15,599 +15,258 @@
 
 from tests import unittest
 from twisted.internet import defer
-from twisted.python.log import PythonLoggingObserver
 
 from synapse.state import StateHandler
-from synapse.storage.pdu import PduEntry
-from synapse.federation.pdu_codec import encode_event_id
-from synapse.federation.units import Pdu
-
-from collections import namedtuple
 
 from mock import Mock
 
-import mock
-
-
-ReturnType = namedtuple(
-    "StateReturnType", ["new_branch", "current_branch"]
-)
-
-
-def _gen_get_power_level(power_level_list):
-    def get_power_level(room_id, user_id):
-        return defer.succeed(power_level_list.get(user_id, None))
-    return get_power_level
 
 class StateTestCase(unittest.TestCase):
     def setUp(self):
-        self.persistence = Mock(spec=[
-            "get_unresolved_state_tree",
-            "update_current_state",
-            "get_latest_pdus_in_context",
-            "get_current_state_pdu",
-            "get_pdu",
-            "get_power_level",
-        ])
-        self.replication = Mock(spec=["get_pdu"])
-
-        hs = Mock(spec=["get_datastore", "get_replication_layer"])
-        hs.get_datastore.return_value = self.persistence
-        hs.get_replication_layer.return_value = self.replication
-        hs.hostname = "bob.com"
-
-        self.state = StateHandler(hs)
-
-    @defer.inlineCallbacks
-    def test_new_state_key(self):
-        # We've never seen anything for this state before
-        new_pdu = new_fake_pdu("A", "test", "mem", "x", None, "u")
-
-        self.persistence.get_power_level.side_effect = _gen_get_power_level({})
-
-        self.persistence.get_unresolved_state_tree.return_value = (
-            (ReturnType([new_pdu], []), None)
-        )
-
-        is_new = yield self.state.handle_new_state(new_pdu)
-
-        self.assertTrue(is_new)
-
-        self.persistence.get_unresolved_state_tree.assert_called_once_with(
-            new_pdu
-        )
-
-        self.assertEqual(1, self.persistence.update_current_state.call_count)
-
-        self.assertFalse(self.replication.get_pdu.called)
-
-    @defer.inlineCallbacks
-    def test_direct_overwrite(self):
-        # We do a direct overwriting of the old state, i.e., the new state
-        # points to the old state.
-
-        old_pdu = new_fake_pdu("A", "test", "mem", "x", None, "u1")
-        new_pdu = new_fake_pdu("B", "test", "mem", "x", "A", "u2")
-
-        self.persistence.get_power_level.side_effect = _gen_get_power_level({
-            "u1": 10,
-            "u2": 5,
-        })
-
-        self.persistence.get_unresolved_state_tree.return_value = (
-            (ReturnType([new_pdu, old_pdu], [old_pdu]), None)
-        )
-
-        is_new = yield self.state.handle_new_state(new_pdu)
-
-        self.assertTrue(is_new)
-
-        self.persistence.get_unresolved_state_tree.assert_called_once_with(
-            new_pdu
+        self.store = Mock(
+            spec_set=[
+                "get_state_groups",
+            ]
         )
+        hs = Mock(spec=["get_datastore"])
+        hs.get_datastore.return_value = self.store
 
-        self.assertEqual(1, self.persistence.update_current_state.call_count)
-
-        self.assertFalse(self.replication.get_pdu.called)
+        self.state = StateHandler(hs)
+        self.event_id = 0
 
     @defer.inlineCallbacks
-    def test_overwrite(self):
-        old_pdu_1 = new_fake_pdu("A", "test", "mem", "x", None, "u1")
-        old_pdu_2 = new_fake_pdu("B", "test", "mem", "x", "A", "u2")
-        new_pdu = new_fake_pdu("C", "test", "mem", "x", "B", "u3")
-
-        self.persistence.get_power_level.side_effect = _gen_get_power_level({
-            "u1": 10,
-            "u2": 5,
-            "u3": 0,
-        })
-
-        self.persistence.get_unresolved_state_tree.return_value = (
-            (ReturnType([new_pdu, old_pdu_2, old_pdu_1], [old_pdu_1]), None)
-        )
+    def test_annotate_with_old_message(self):
+        event = self.create_event(type="test_message", name="event")
 
-        is_new = yield self.state.handle_new_state(new_pdu)
+        old_state = [
+            self.create_event(type="test1", state_key="1"),
+            self.create_event(type="test1", state_key="2"),
+            self.create_event(type="test2", state_key=""),
+        ]
 
-        self.assertTrue(is_new)
+        yield self.state.annotate_event_with_state(event, old_state=old_state)
 
-        self.persistence.get_unresolved_state_tree.assert_called_once_with(
-            new_pdu
-        )
+        for k, v in event.old_state_events.items():
+            type, state_key = k
+            self.assertEqual(type, v.type)
+            self.assertEqual(state_key, v.state_key)
 
-        self.assertEqual(1, self.persistence.update_current_state.call_count)
+        self.assertEqual(set(old_state), set(event.old_state_events.values()))
+        self.assertDictEqual(event.old_state_events, event.state_events)
 
-        self.assertFalse(self.replication.get_pdu.called)
+        self.assertIsNone(event.state_group)
 
     @defer.inlineCallbacks
-    def test_power_level_fail(self):
-        # We try to update the state based on an outdated state, and have a
-        # too low power level.
-
-        old_pdu_1 = new_fake_pdu("A", "test", "mem", "x", None, "u1")
-        old_pdu_2 = new_fake_pdu("B", "test", "mem", "x", None, "u2")
-        new_pdu = new_fake_pdu("C", "test", "mem", "x", "A", "u3")
-
-        self.persistence.get_power_level.side_effect = _gen_get_power_level({
-            "u1": 10,
-            "u2": 10,
-            "u3": 5,
-        })
-
-        self.persistence.get_unresolved_state_tree.return_value = (
-            (ReturnType([new_pdu, old_pdu_1], [old_pdu_2, old_pdu_1]), None)
-        )
-
-        is_new = yield self.state.handle_new_state(new_pdu)
-
-        self.assertFalse(is_new)
-
-        self.persistence.get_unresolved_state_tree.assert_called_once_with(
-            new_pdu
-        )
-
-        self.assertEqual(0, self.persistence.update_current_state.call_count)
+    def test_annotate_with_old_state(self):
+        event = self.create_event(type="state", state_key="", name="event")
 
-        self.assertFalse(self.replication.get_pdu.called)
-
-    @defer.inlineCallbacks
-    def test_power_level_succeed(self):
-        # We try to update the state based on an outdated state, but have
-        # sufficient power level to force the update.
-
-        old_pdu_1 = new_fake_pdu("A", "test", "mem", "x", None, "u1")
-        old_pdu_2 = new_fake_pdu("B", "test", "mem", "x", None, "u2")
-        new_pdu = new_fake_pdu("C", "test", "mem", "x", "A", "u3")
-
-        self.persistence.get_power_level.side_effect = _gen_get_power_level({
-            "u1": 10,
-            "u2": 10,
-            "u3": 15,
-        })
-
-        self.persistence.get_unresolved_state_tree.return_value = (
-            (ReturnType([new_pdu, old_pdu_1], [old_pdu_2, old_pdu_1]), None)
-        )
+        old_state = [
+            self.create_event(type="test1", state_key="1"),
+            self.create_event(type="test1", state_key="2"),
+            self.create_event(type="test2", state_key=""),
+        ]
 
-        is_new = yield self.state.handle_new_state(new_pdu)
+        yield self.state.annotate_event_with_state(event, old_state=old_state)
 
-        self.assertTrue(is_new)
+        for k, v in event.old_state_events.items():
+            type, state_key = k
+            self.assertEqual(type, v.type)
+            self.assertEqual(state_key, v.state_key)
 
-        self.persistence.get_unresolved_state_tree.assert_called_once_with(
-            new_pdu
+        self.assertEqual(
+            set(old_state + [event]),
+            set(event.old_state_events.values())
         )
 
-        self.assertEqual(1, self.persistence.update_current_state.call_count)
+        self.assertDictEqual(event.old_state_events, event.state_events)
 
-        self.assertFalse(self.replication.get_pdu.called)
+        self.assertIsNone(event.state_group)
 
     @defer.inlineCallbacks
-    def test_power_level_equal_same_len(self):
-        # We try to update the state based on an outdated state, the power
-        # levels are the same and so are the branch lengths
-
-        old_pdu_1 = new_fake_pdu("A", "test", "mem", "x", None, "u1")
-        old_pdu_2 = new_fake_pdu("B", "test", "mem", "x", None, "u2")
-        new_pdu = new_fake_pdu("C", "test", "mem", "x", "A", "u3")
-
-        self.persistence.get_power_level.side_effect = _gen_get_power_level({
-            "u1": 10,
-            "u2": 10,
-            "u3": 10,
-        })
-
-        self.persistence.get_unresolved_state_tree.return_value = (
-            (ReturnType([new_pdu, old_pdu_1], [old_pdu_2, old_pdu_1]), None)
-        )
-
-        is_new = yield self.state.handle_new_state(new_pdu)
+    def test_trivial_annotate_message(self):
+        event = self.create_event(type="test_message", name="event")
+        event.prev_events = []
+
+        old_state = [
+            self.create_event(type="test1", state_key="1"),
+            self.create_event(type="test1", state_key="2"),
+            self.create_event(type="test2", state_key=""),
+        ]
 
-        self.assertTrue(is_new)
+        group_name = "group_name_1"
 
-        self.persistence.get_unresolved_state_tree.assert_called_once_with(
-            new_pdu
-        )
+        self.store.get_state_groups.return_value = {
+            group_name: old_state,
+        }
 
-        self.assertEqual(1, self.persistence.update_current_state.call_count)
+        yield self.state.annotate_event_with_state(event)
 
-        self.assertFalse(self.replication.get_pdu.called)
+        for k, v in event.old_state_events.items():
+            type, state_key = k
+            self.assertEqual(type, v.type)
+            self.assertEqual(state_key, v.state_key)
 
-    @defer.inlineCallbacks
-    def test_power_level_equal_diff_len(self):
-        # We try to update the state based on an outdated state, the power
-        # levels are the same but the branch length of the new one is longer.
-
-        old_pdu_1 = new_fake_pdu("A", "test", "mem", "x", None, "u1")
-        old_pdu_2 = new_fake_pdu("B", "test", "mem", "x", None, "u2")
-        old_pdu_3 = new_fake_pdu("C", "test", "mem", "x", "A", "u3")
-        new_pdu = new_fake_pdu("D", "test", "mem", "x", "C", "u4")
-
-        self.persistence.get_power_level.side_effect = _gen_get_power_level({
-            "u1": 10,
-            "u2": 10,
-            "u3": 10,
-            "u4": 10,
-        })
-
-        self.persistence.get_unresolved_state_tree.return_value = (
-            (
-                ReturnType(
-                    [new_pdu, old_pdu_3, old_pdu_1],
-                    [old_pdu_2, old_pdu_1]
-                ),
-                None
-            )
+        self.assertEqual(
+            set([e.event_id for e in old_state]),
+            set([e.event_id for e in event.old_state_events.values()])
         )
 
-        is_new = yield self.state.handle_new_state(new_pdu)
-
-        self.assertTrue(is_new)
-
-        self.persistence.get_unresolved_state_tree.assert_called_once_with(
-            new_pdu
+        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(1, self.persistence.update_current_state.call_count)
-
-        self.assertFalse(self.replication.get_pdu.called)
+        self.assertEqual(group_name, event.state_group)
 
     @defer.inlineCallbacks
-    def test_missing_pdu(self):
-        # We try to update state against a PDU we haven't yet seen,
-        # triggering a get_pdu request
-
-        # The pdu we haven't seen
-        old_pdu_1 = new_fake_pdu(
-            "A", "test", "mem", "x", None, "u1", depth=0
-        )
-
-        old_pdu_2 = new_fake_pdu(
-            "B", "test", "mem", "x", "A", "u2", depth=1
-        )
-        new_pdu = new_fake_pdu(
-            "C", "test", "mem", "x", "A", "u3", depth=2
-        )
-
-        self.persistence.get_power_level.side_effect = _gen_get_power_level({
-            "u1": 10,
-            "u2": 10,
-            "u3": 20,
-        })
-
-        # The return_value of `get_unresolved_state_tree`, which changes after
-        # the call to get_pdu
-        tree_to_return = [(ReturnType([new_pdu], [old_pdu_2]), 0)]
-
-        def return_tree(p):
-            return tree_to_return[0]
-
-        def set_return_tree(destination, pdu_origin, pdu_id, outlier=False):
-            tree_to_return[0] = (
-                ReturnType(
-                    [new_pdu, old_pdu_1], [old_pdu_2, old_pdu_1]
-                ),
-                None
-            )
-            return defer.succeed(None)
-
-        self.persistence.get_unresolved_state_tree.side_effect = return_tree
+    def test_trivial_annotate_state(self):
+        event = self.create_event(type="state", state_key="", name="event")
+        event.prev_events = []
+
+        old_state = [
+            self.create_event(type="test1", state_key="1"),
+            self.create_event(type="test1", state_key="2"),
+            self.create_event(type="test2", state_key=""),
+        ]
 
-        self.replication.get_pdu.side_effect = set_return_tree
+        group_name = "group_name_1"
 
-        self.persistence.get_pdu.return_value = None
+        self.store.get_state_groups.return_value = {
+            group_name: old_state,
+        }
 
-        is_new = yield self.state.handle_new_state(new_pdu)
+        yield self.state.annotate_event_with_state(event)
 
-        self.assertTrue(is_new)
+        for k, v in event.old_state_events.items():
+            type, state_key = k
+            self.assertEqual(type, v.type)
+            self.assertEqual(state_key, v.state_key)
 
-        self.replication.get_pdu.assert_called_with(
-            destination=new_pdu.origin,
-            pdu_origin=old_pdu_1.origin,
-            pdu_id=old_pdu_1.pdu_id,
-            outlier=True
+        self.assertEqual(
+            set([e.event_id for e in old_state]),
+            set([e.event_id for e in event.old_state_events.values()])
         )
 
-        self.persistence.get_unresolved_state_tree.assert_called_with(
-            new_pdu
+        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()])
         )
 
-        self.assertEquals(
-            2, self.persistence.get_unresolved_state_tree.call_count
+        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
         )
 
-        self.assertEqual(1, self.persistence.update_current_state.call_count)
+        self.assertIsNone(event.state_group)
 
     @defer.inlineCallbacks
-    def test_missing_pdu_depth_1(self):
-        # We try to update state against a PDU we haven't yet seen,
-        # triggering a get_pdu request
-
-        # The pdu we haven't seen
-        old_pdu_1 = new_fake_pdu(
-            "A", "test", "mem", "x", None, "u1", depth=0
-        )
-
-        old_pdu_2 = new_fake_pdu(
-            "B", "test", "mem", "x", "A", "u2", depth=2
-        )
-        old_pdu_3 = new_fake_pdu(
-            "C", "test", "mem", "x", "B", "u3", depth=3
-        )
-        new_pdu = new_fake_pdu(
-            "D", "test", "mem", "x", "A", "u4", depth=4
-        )
-
-        self.persistence.get_power_level.side_effect = _gen_get_power_level({
-            "u1": 10,
-            "u2": 10,
-            "u3": 10,
-            "u4": 20,
-        })
-
-        # The return_value of `get_unresolved_state_tree`, which changes after
-        # the call to get_pdu
-        tree_to_return = [
-            (
-                ReturnType([new_pdu], [old_pdu_3]),
-                0
-            ),
-            (
-                ReturnType(
-                    [new_pdu, old_pdu_1], [old_pdu_3]
-                ),
-                1
-            ),
-            (
-                ReturnType(
-                    [new_pdu, old_pdu_1], [old_pdu_3, old_pdu_2, old_pdu_1]
-                ),
-                None
-            ),
+    def test_resolve_message_conflict(self):
+        event = self.create_event(type="test_message", name="event")
+        event.prev_events = []
+
+        old_state_1 = [
+            self.create_event(type="test1", state_key="1"),
+            self.create_event(type="test1", state_key="2"),
+            self.create_event(type="test2", state_key=""),
         ]
 
-        to_return = [0]
-
-        def return_tree(p):
-            return tree_to_return[to_return[0]]
-
-        def set_return_tree(destination, pdu_origin, pdu_id, outlier=False):
-            to_return[0] += 1
-            return defer.succeed(None)
-
-        self.persistence.get_unresolved_state_tree.side_effect = return_tree
-
-        self.replication.get_pdu.side_effect = set_return_tree
-
-        self.persistence.get_pdu.return_value = None
-
-        is_new = yield self.state.handle_new_state(new_pdu)
+        old_state_2 = [
+            self.create_event(type="test1", state_key="1"),
+            self.create_event(type="test3", state_key="2"),
+            self.create_event(type="test4", state_key=""),
+        ]
 
-        self.assertTrue(is_new)
+        group_name_1 = "group_name_1"
+        group_name_2 = "group_name_2"
 
-        self.assertEqual(2, self.replication.get_pdu.call_count)
+        self.store.get_state_groups.return_value = {
+            group_name_1: old_state_1,
+            group_name_2: old_state_2,
+        }
 
-        self.replication.get_pdu.assert_has_calls(
-            [
-                mock.call(
-                    destination=new_pdu.origin,
-                    pdu_origin=old_pdu_1.origin,
-                    pdu_id=old_pdu_1.pdu_id,
-                    outlier=True
-                ),
-                mock.call(
-                    destination=old_pdu_3.origin,
-                    pdu_origin=old_pdu_2.origin,
-                    pdu_id=old_pdu_2.pdu_id,
-                    outlier=True
-                ),
-            ]
-        )
+        yield self.state.annotate_event_with_state(event)
 
-        self.persistence.get_unresolved_state_tree.assert_called_with(
-            new_pdu
-        )
+        self.assertEqual(len(event.old_state_events), 5)
 
-        self.assertEquals(
-            3, self.persistence.get_unresolved_state_tree.call_count
+        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(1, self.persistence.update_current_state.call_count)
+        self.assertIsNone(event.state_group)
 
     @defer.inlineCallbacks
-    def test_missing_pdu_depth_2(self):
-        # We try to update state against a PDU we haven't yet seen,
-        # triggering a get_pdu request
-
-        # The pdu we haven't seen
-        old_pdu_1 = new_fake_pdu(
-            "A", "test", "mem", "x", None, "u1", depth=0
-        )
-
-        old_pdu_2 = new_fake_pdu(
-            "B", "test", "mem", "x", "A", "u2", depth=2
-        )
-        old_pdu_3 = new_fake_pdu(
-            "C", "test", "mem", "x", "B", "u3", depth=3
-        )
-        new_pdu = new_fake_pdu(
-            "D", "test", "mem", "x", "A", "u4", depth=1
-        )
-
-        self.persistence.get_power_level.side_effect = _gen_get_power_level({
-            "u1": 10,
-            "u2": 10,
-            "u3": 10,
-            "u4": 20,
-        })
-
-        # The return_value of `get_unresolved_state_tree`, which changes after
-        # the call to get_pdu
-        tree_to_return = [
-            (
-                ReturnType([new_pdu], [old_pdu_3]),
-                1,
-            ),
-            (
-                ReturnType(
-                    [new_pdu], [old_pdu_3, old_pdu_2]
-                ),
-                0,
-            ),
-            (
-                ReturnType(
-                    [new_pdu, old_pdu_1], [old_pdu_3, old_pdu_2, old_pdu_1]
-                ),
-                None
-            ),
+    def test_resolve_state_conflict(self):
+        event = self.create_event(type="test4", state_key="", name="event")
+        event.prev_events = []
+
+        old_state_1 = [
+            self.create_event(type="test1", state_key="1"),
+            self.create_event(type="test1", state_key="2"),
+            self.create_event(type="test2", state_key=""),
         ]
 
-        to_return = [0]
-
-        def return_tree(p):
-            return tree_to_return[to_return[0]]
-
-        def set_return_tree(destination, pdu_origin, pdu_id, outlier=False):
-            to_return[0] += 1
-            return defer.succeed(None)
-
-        self.persistence.get_unresolved_state_tree.side_effect = return_tree
-
-        self.replication.get_pdu.side_effect = set_return_tree
-
-        self.persistence.get_pdu.return_value = None
-
-        is_new = yield self.state.handle_new_state(new_pdu)
-
-        self.assertTrue(is_new)
-
-        self.assertEqual(2, self.replication.get_pdu.call_count)
-
-        self.replication.get_pdu.assert_has_calls(
-            [
-                mock.call(
-                    destination=old_pdu_3.origin,
-                    pdu_origin=old_pdu_2.origin,
-                    pdu_id=old_pdu_2.pdu_id,
-                    outlier=True
-                ),
-                mock.call(
-                    destination=new_pdu.origin,
-                    pdu_origin=old_pdu_1.origin,
-                    pdu_id=old_pdu_1.pdu_id,
-                    outlier=True
-                ),
-            ]
-        )
-
-        self.persistence.get_unresolved_state_tree.assert_called_with(
-            new_pdu
-        )
-
-        self.assertEquals(
-            3, self.persistence.get_unresolved_state_tree.call_count
-        )
-
-        self.assertEqual(1, self.persistence.update_current_state.call_count)
-
-    @defer.inlineCallbacks
-    def test_no_common_ancestor(self):
-        # We do a direct overwriting of the old state, i.e., the new state
-        # points to the old state.
+        old_state_2 = [
+            self.create_event(type="test1", state_key="1"),
+            self.create_event(type="test3", state_key="2"),
+            self.create_event(type="test4", state_key=""),
+        ]
 
-        old_pdu = new_fake_pdu("A", "test", "mem", "x", None, "u1")
-        new_pdu = new_fake_pdu("B", "test", "mem", "x", None, "u2")
+        group_name_1 = "group_name_1"
+        group_name_2 = "group_name_2"
 
-        self.persistence.get_power_level.side_effect = _gen_get_power_level({
-            "u1": 5,
-            "u2": 10,
-        })
+        self.store.get_state_groups.return_value = {
+            group_name_1: old_state_1,
+            group_name_2: old_state_2,
+        }
 
-        self.persistence.get_unresolved_state_tree.return_value = (
-            (ReturnType([new_pdu], [old_pdu]), None)
-        )
+        yield self.state.annotate_event_with_state(event)
 
-        is_new = yield self.state.handle_new_state(new_pdu)
+        self.assertEqual(len(event.old_state_events), 5)
 
-        self.assertTrue(is_new)
+        expected_new = event.old_state_events
+        expected_new[(event.type, event.state_key)] = event
 
-        self.persistence.get_unresolved_state_tree.assert_called_once_with(
-            new_pdu
+        self.assertEqual(
+            set([e.event_id for e in expected_new.values()]),
+            set([e.event_id for e in event.state_events.values()]),
         )
 
-        self.assertEqual(1, self.persistence.update_current_state.call_count)
-
-        self.assertFalse(self.replication.get_pdu.called)
-
-    @defer.inlineCallbacks
-    def test_new_event(self):
-        event = Mock()
-        event.event_id = "12123123@test"
+        self.assertIsNone(event.state_group)
 
-        state_pdu = new_fake_pdu("C", "test", "mem", "x", "A", 20)
+    def create_event(self, name=None, type=None, state_key=None):
+        self.event_id += 1
+        event_id = str(self.event_id)
 
-        snapshot = Mock()
-        snapshot.prev_state_pdu = state_pdu
-        event_id = "pdu_id@origin.com"
+        if not name:
+            if state_key is not None:
+                name = "<%s-%s>" % (type, state_key)
+            else:
+                name = "<%s>" % (type, )
 
-        def fill_out_prev_events(event):
-            event.prev_events = [event_id]
-            event.depth = 6
-        snapshot.fill_out_prev_events = fill_out_prev_events
+        event = Mock(name=name, spec=[])
+        event.type = type
 
-        yield self.state.handle_new_event(event, snapshot)
-
-        self.assertLess(5, event.depth)
-
-        self.assertEquals(1, len(event.prev_events))
-
-        prev_id = event.prev_events[0]
-
-        self.assertEqual(event_id, prev_id)
-
-        self.assertEqual(
-            encode_event_id(state_pdu.pdu_id, state_pdu.origin),
-            event.prev_state
-        )
+        if state_key is not None:
+            event.state_key = state_key
+        event.event_id = event_id
 
+        event.user_id = "@user_id:example.com"
+        event.room_id = "!room_id:example.com"
 
-def new_fake_pdu(pdu_id, context, pdu_type, state_key, prev_state_id,
-                 user_id, depth=0):
-    new_pdu = Pdu(
-        pdu_id=pdu_id,
-        pdu_type=pdu_type,
-        state_key=state_key,
-        user_id=user_id,
-        prev_state_id=prev_state_id,
-        origin="example.com",
-        context="context",
-        origin_server_ts=1405353060021,
-        depth=depth,
-        content_json="{}",
-        unrecognized_keys="{}",
-        outlier=True,
-        is_state=True,
-        prev_state_origin="example.com",
-        have_processed=True,
-        content={},
-    )
-
-    return new_pdu
+        return event
diff --git a/tests/util/test_log_context.py b/tests/util/test_log_context.py
new file mode 100644
index 0000000000..efa0f28bad
--- /dev/null
+++ b/tests/util/test_log_context.py
@@ -0,0 +1,43 @@
+from twisted.internet import defer
+from twisted.internet import reactor
+from .. import unittest
+
+from synapse.util.async import sleep
+from synapse.util.logcontext import LoggingContext
+
+class LoggingContextTestCase(unittest.TestCase):
+
+    def _check_test_key(self, value):
+        self.assertEquals(
+            LoggingContext.current_context().test_key, value
+        )
+
+    def test_with_context(self):
+        with LoggingContext() as context_one:
+            context_one.test_key = "test"
+            self._check_test_key("test")
+
+    def test_chaining(self):
+        with LoggingContext() as context_one:
+            context_one.test_key = "one"
+            with LoggingContext() as context_two:
+                self._check_test_key("one")
+                context_two.test_key = "two"
+                self._check_test_key("two")
+            self._check_test_key("one")
+
+    @defer.inlineCallbacks
+    def test_sleep(self):
+        @defer.inlineCallbacks
+        def competing_callback():
+            with LoggingContext() as competing_context:
+                competing_context.test_key = "competing"
+                yield sleep(0)
+                self._check_test_key("competing")
+
+        reactor.callLater(0, competing_callback)
+
+        with LoggingContext() as context_one:
+            context_one.test_key = "one"
+            yield sleep(0)
+            self._check_test_key("one")
diff --git a/tests/utils.py b/tests/utils.py
index 60fd6085ac..d8be73dba8 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -118,13 +118,14 @@ class MockHttpResource(HttpServer):
 class MockKey(object):
     alg = "mock_alg"
     version = "mock_version"
+    signature = b"\x9a\x87$"
 
     @property
     def verify_key(self):
         return self
 
     def sign(self, message):
-        return b"\x9a\x87$"
+        return self
 
     def verify(self, message, sig):
         assert sig == b"\x9a\x87$"