summary refs log tree commit diff
path: root/tests
diff options
context:
space:
mode:
authorMatthew Hodgson <matthew@matrix.org>2016-02-10 16:27:15 +0000
committerMatthew Hodgson <matthew@matrix.org>2016-02-10 16:27:15 +0000
commit76346870571ce885d07b180cf88c11a33a051cf8 (patch)
tree832664ad8351517a43bd91230eeacf257b2c0bec /tests
parenttry to bump syweb to 0.6.8 (diff)
parentMerge branch 'release-v0.13.0' of github.com:matrix-org/synapse (diff)
downloadsynapse-76346870571ce885d07b180cf88c11a33a051cf8.tar.xz
Merge branch 'master' of git+ssh://github.com/matrix-org/synapse
Diffstat (limited to 'tests')
-rw-r--r--tests/__init__.py2
-rw-r--r--tests/api/test_auth.py30
-rw-r--r--tests/api/test_filtering.py21
-rw-r--r--tests/appservice/__init__.py2
-rw-r--r--tests/appservice/test_appservice.py3
-rw-r--r--tests/appservice/test_scheduler.py2
-rw-r--r--tests/config/__init__.py14
-rw-r--r--tests/config/test_generate.py50
-rw-r--r--tests/config/test_load.py78
-rw-r--r--tests/crypto/__init__.py2
-rw-r--r--tests/crypto/test_event_signing.py2
-rw-r--r--tests/events/test_utils.py2
-rw-r--r--tests/federation/__init__.py0
-rw-r--r--tests/federation/test_federation.py303
-rw-r--r--tests/handlers/test_appservice.py2
-rw-r--r--tests/handlers/test_auth.py2
-rw-r--r--tests/handlers/test_directory.py2
-rw-r--r--tests/handlers/test_federation.py130
-rw-r--r--tests/handlers/test_presence.py3
-rw-r--r--tests/handlers/test_presencelike.py2
-rw-r--r--tests/handlers/test_profile.py2
-rw-r--r--tests/handlers/test_room.py404
-rw-r--r--tests/handlers/test_typing.py3
-rw-r--r--tests/metrics/test_metric.py2
-rw-r--r--tests/rest/__init__.py2
-rw-r--r--tests/rest/client/__init__.py2
-rw-r--r--tests/rest/client/v1/__init__.py2
-rw-r--r--tests/rest/client/v1/test_events.py4
-rw-r--r--tests/rest/client/v1/test_presence.py25
-rw-r--r--tests/rest/client/v1/test_profile.py9
-rw-r--r--tests/rest/client/v1/test_rooms.py15
-rw-r--r--tests/rest/client/v1/test_typing.py2
-rw-r--r--tests/rest/client/v1/utils.py2
-rw-r--r--tests/rest/client/v2_alpha/__init__.py2
-rw-r--r--tests/rest/client/v2_alpha/test_filter.py2
-rw-r--r--tests/rest/client/v2_alpha/test_register.py4
-rw-r--r--tests/storage/event_injector.py2
-rw-r--r--tests/storage/test__base.py2
-rw-r--r--tests/storage/test_appservice.py103
-rw-r--r--tests/storage/test_base.py2
-rw-r--r--tests/storage/test_directory.py2
-rw-r--r--tests/storage/test_events.py2
-rw-r--r--tests/storage/test_presence.py2
-rw-r--r--tests/storage/test_profile.py2
-rw-r--r--tests/storage/test_redaction.py2
-rw-r--r--tests/storage/test_registration.py7
-rw-r--r--tests/storage/test_room.py28
-rw-r--r--tests/storage/test_roommember.py2
-rw-r--r--tests/storage/test_stream.py2
-rw-r--r--tests/test_distributor.py2
-rw-r--r--tests/test_dns.py115
-rw-r--r--tests/test_state.py2
-rw-r--r--tests/test_test_utils.py2
-rw-r--r--tests/test_types.py7
-rw-r--r--tests/unittest.py2
-rw-r--r--tests/util/__init__.py2
-rw-r--r--tests/util/test_dict_cache.py2
-rw-r--r--tests/util/test_log_context.py10
-rw-r--r--tests/util/test_lrucache.py29
-rw-r--r--tests/util/test_snapshot_cache.py2
-rw-r--r--tests/util/test_treecache.py78
-rw-r--r--tests/utils.py31
62 files changed, 582 insertions, 994 deletions
diff --git a/tests/__init__.py b/tests/__init__.py
index 9bff9ec169..d0e9399dda 100644
--- a/tests/__init__.py
+++ b/tests/__init__.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2014 OpenMarket Ltd
+# Copyright 2014-2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/tests/api/test_auth.py b/tests/api/test_auth.py
index 70d928defe..474c5c418f 100644
--- a/tests/api/test_auth.py
+++ b/tests/api/test_auth.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2015 OpenMarket Ltd
+# Copyright 2015 - 2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -51,8 +51,8 @@ class AuthTestCase(unittest.TestCase):
         request = Mock(args={})
         request.args["access_token"] = [self.test_token]
         request.requestHeaders.getRawHeaders = Mock(return_value=[""])
-        (user, _, _) = yield self.auth.get_user_by_req(request)
-        self.assertEquals(user.to_string(), self.test_user)
+        requester = yield self.auth.get_user_by_req(request)
+        self.assertEquals(requester.user.to_string(), self.test_user)
 
     def test_get_user_by_req_user_bad_token(self):
         self.store.get_app_service_by_token = Mock(return_value=None)
@@ -86,8 +86,8 @@ class AuthTestCase(unittest.TestCase):
         request = Mock(args={})
         request.args["access_token"] = [self.test_token]
         request.requestHeaders.getRawHeaders = Mock(return_value=[""])
-        (user, _, _) = yield self.auth.get_user_by_req(request)
-        self.assertEquals(user.to_string(), self.test_user)
+        requester = yield self.auth.get_user_by_req(request)
+        self.assertEquals(requester.user.to_string(), self.test_user)
 
     def test_get_user_by_req_appservice_bad_token(self):
         self.store.get_app_service_by_token = Mock(return_value=None)
@@ -121,8 +121,8 @@ class AuthTestCase(unittest.TestCase):
         request.args["access_token"] = [self.test_token]
         request.args["user_id"] = [masquerading_user_id]
         request.requestHeaders.getRawHeaders = Mock(return_value=[""])
-        (user, _, _) = yield self.auth.get_user_by_req(request)
-        self.assertEquals(user.to_string(), masquerading_user_id)
+        requester = yield self.auth.get_user_by_req(request)
+        self.assertEquals(requester.user.to_string(), masquerading_user_id)
 
     def test_get_user_by_req_appservice_valid_token_bad_user_id(self):
         masquerading_user_id = "@doppelganger:matrix.org"
@@ -154,7 +154,7 @@ class AuthTestCase(unittest.TestCase):
         macaroon.add_first_party_caveat("gen = 1")
         macaroon.add_first_party_caveat("type = access")
         macaroon.add_first_party_caveat("user_id = %s" % (user_id,))
-        user_info = yield self.auth._get_user_from_macaroon(macaroon.serialize())
+        user_info = yield self.auth.get_user_from_macaroon(macaroon.serialize())
         user = user_info["user"]
         self.assertEqual(UserID.from_string(user_id), user)
 
@@ -171,7 +171,7 @@ class AuthTestCase(unittest.TestCase):
         macaroon.add_first_party_caveat("guest = true")
         serialized = macaroon.serialize()
 
-        user_info = yield self.auth._get_user_from_macaroon(serialized)
+        user_info = yield self.auth.get_user_from_macaroon(serialized)
         user = user_info["user"]
         is_guest = user_info["is_guest"]
         self.assertEqual(UserID.from_string(user_id), user)
@@ -192,7 +192,7 @@ class AuthTestCase(unittest.TestCase):
         macaroon.add_first_party_caveat("type = access")
         macaroon.add_first_party_caveat("user_id = %s" % (user,))
         with self.assertRaises(AuthError) as cm:
-            yield self.auth._get_user_from_macaroon(macaroon.serialize())
+            yield self.auth.get_user_from_macaroon(macaroon.serialize())
         self.assertEqual(401, cm.exception.code)
         self.assertIn("User mismatch", cm.exception.msg)
 
@@ -212,7 +212,7 @@ class AuthTestCase(unittest.TestCase):
         macaroon.add_first_party_caveat("type = access")
 
         with self.assertRaises(AuthError) as cm:
-            yield self.auth._get_user_from_macaroon(macaroon.serialize())
+            yield self.auth.get_user_from_macaroon(macaroon.serialize())
         self.assertEqual(401, cm.exception.code)
         self.assertIn("No user caveat", cm.exception.msg)
 
@@ -234,7 +234,7 @@ class AuthTestCase(unittest.TestCase):
         macaroon.add_first_party_caveat("user_id = %s" % (user,))
 
         with self.assertRaises(AuthError) as cm:
-            yield self.auth._get_user_from_macaroon(macaroon.serialize())
+            yield self.auth.get_user_from_macaroon(macaroon.serialize())
         self.assertEqual(401, cm.exception.code)
         self.assertIn("Invalid macaroon", cm.exception.msg)
 
@@ -257,7 +257,7 @@ class AuthTestCase(unittest.TestCase):
         macaroon.add_first_party_caveat("cunning > fox")
 
         with self.assertRaises(AuthError) as cm:
-            yield self.auth._get_user_from_macaroon(macaroon.serialize())
+            yield self.auth.get_user_from_macaroon(macaroon.serialize())
         self.assertEqual(401, cm.exception.code)
         self.assertIn("Invalid macaroon", cm.exception.msg)
 
@@ -285,11 +285,11 @@ class AuthTestCase(unittest.TestCase):
 
         self.hs.clock.now = 5000 # seconds
 
-        yield self.auth._get_user_from_macaroon(macaroon.serialize())
+        yield self.auth.get_user_from_macaroon(macaroon.serialize())
         # TODO(daniel): Turn on the check that we validate expiration, when we
         # validate expiration (and remove the above line, which will start
         # throwing).
         # with self.assertRaises(AuthError) as cm:
-        #     yield self.auth._get_user_from_macaroon(macaroon.serialize())
+        #     yield self.auth.get_user_from_macaroon(macaroon.serialize())
         # self.assertEqual(401, cm.exception.code)
         # self.assertIn("Invalid macaroon", cm.exception.msg)
diff --git a/tests/api/test_filtering.py b/tests/api/test_filtering.py
index 9f9af2d783..ceb0089268 100644
--- a/tests/api/test_filtering.py
+++ b/tests/api/test_filtering.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2015 OpenMarket Ltd
+# Copyright 2015, 2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -13,26 +13,24 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from collections import namedtuple
 from tests import unittest
 from twisted.internet import defer
 
-from mock import Mock, NonCallableMock
+from mock import Mock
 from tests.utils import (
     MockHttpResource, DeferredMockCallable, setup_test_homeserver
 )
 
 from synapse.types import UserID
-from synapse.api.filtering import FilterCollection, Filter
+from synapse.api.filtering import Filter
+from synapse.events import FrozenEvent
 
 user_localpart = "test_user"
 # MockEvent = namedtuple("MockEvent", "sender type room_id")
 
 
 def MockEvent(**kwargs):
-    ev = NonCallableMock(spec_set=kwargs.keys())
-    ev.configure_mock(**kwargs)
-    return ev
+    return FrozenEvent(kwargs)
 
 
 class FilteringTestCase(unittest.TestCase):
@@ -384,19 +382,20 @@ class FilteringTestCase(unittest.TestCase):
                 "types": ["m.*"]
             }
         }
-        user = UserID.from_string("@" + user_localpart + ":test")
+
         filter_id = yield self.datastore.add_user_filter(
-            user_localpart=user_localpart,
+            user_localpart=user_localpart + "2",
             user_filter=user_filter_json,
         )
         event = MockEvent(
+            event_id="$asdasd:localhost",
             sender="@foo:bar",
             type="custom.avatar.3d.crazy",
         )
         events = [event]
 
         user_filter = yield self.filtering.get_user_filter(
-            user_localpart=user_localpart,
+            user_localpart=user_localpart + "2",
             filter_id=filter_id,
         )
 
@@ -504,4 +503,4 @@ class FilteringTestCase(unittest.TestCase):
             filter_id=filter_id,
         )
 
-        self.assertEquals(filter.filter_json, user_filter_json)
+        self.assertEquals(filter.get_filter_json(), user_filter_json)
diff --git a/tests/appservice/__init__.py b/tests/appservice/__init__.py
index 1a84d94cd9..fe0ac3f8e9 100644
--- a/tests/appservice/__init__.py
+++ b/tests/appservice/__init__.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2015 OpenMarket Ltd
+# Copyright 2015, 2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/tests/appservice/test_appservice.py b/tests/appservice/test_appservice.py
index 8ce8dc0a87..ef48bbc296 100644
--- a/tests/appservice/test_appservice.py
+++ b/tests/appservice/test_appservice.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2015 OpenMarket Ltd
+# Copyright 2015, 2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -29,6 +29,7 @@ class ApplicationServiceTestCase(unittest.TestCase):
 
     def setUp(self):
         self.service = ApplicationService(
+            id="unique_identifier",
             url="some_url",
             token="some_token",
             namespaces={
diff --git a/tests/appservice/test_scheduler.py b/tests/appservice/test_scheduler.py
index 82a5965097..c9c2d36210 100644
--- a/tests/appservice/test_scheduler.py
+++ b/tests/appservice/test_scheduler.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2015 OpenMarket Ltd
+# Copyright 2015, 2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/tests/config/__init__.py b/tests/config/__init__.py
new file mode 100644
index 0000000000..b7df13c9ee
--- /dev/null
+++ b/tests/config/__init__.py
@@ -0,0 +1,14 @@
+# -*- coding: utf-8 -*-
+# Copyright 2016 OpenMarket Ltd
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
diff --git a/tests/config/test_generate.py b/tests/config/test_generate.py
new file mode 100644
index 0000000000..4329d73974
--- /dev/null
+++ b/tests/config/test_generate.py
@@ -0,0 +1,50 @@
+# -*- coding: utf-8 -*-
+# Copyright 2016 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.
+import os.path
+import shutil
+import tempfile
+from synapse.config.homeserver import HomeServerConfig
+from tests import unittest
+
+
+class ConfigGenerationTestCase(unittest.TestCase):
+
+    def setUp(self):
+        self.dir = tempfile.mkdtemp()
+        print self.dir
+        self.file = os.path.join(self.dir, "homeserver.yaml")
+
+    def tearDown(self):
+        shutil.rmtree(self.dir)
+
+    def test_generate_config_generates_files(self):
+        HomeServerConfig.load_config("", [
+            "--generate-config",
+            "-c", self.file,
+            "--report-stats=yes",
+            "-H", "lemurs.win"
+        ])
+
+        self.assertSetEqual(
+            set([
+                "homeserver.yaml",
+                "lemurs.win.log.config",
+                "lemurs.win.signing.key",
+                "lemurs.win.tls.crt",
+                "lemurs.win.tls.dh",
+                "lemurs.win.tls.key",
+            ]),
+            set(os.listdir(self.dir))
+        )
diff --git a/tests/config/test_load.py b/tests/config/test_load.py
new file mode 100644
index 0000000000..fbbbf93fef
--- /dev/null
+++ b/tests/config/test_load.py
@@ -0,0 +1,78 @@
+# -*- coding: utf-8 -*-
+# Copyright 2016 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.
+import os.path
+import shutil
+import tempfile
+import yaml
+from synapse.config.homeserver import HomeServerConfig
+from tests import unittest
+
+
+class ConfigLoadingTestCase(unittest.TestCase):
+
+    def setUp(self):
+        self.dir = tempfile.mkdtemp()
+        print self.dir
+        self.file = os.path.join(self.dir, "homeserver.yaml")
+
+    def tearDown(self):
+        shutil.rmtree(self.dir)
+
+    def test_load_fails_if_server_name_missing(self):
+        self.generate_config_and_remove_lines_containing("server_name")
+        with self.assertRaises(Exception):
+            HomeServerConfig.load_config("", ["-c", self.file])
+
+    def test_generates_and_loads_macaroon_secret_key(self):
+        self.generate_config()
+
+        with open(self.file,
+                  "r") as f:
+            raw = yaml.load(f)
+        self.assertIn("macaroon_secret_key", raw)
+
+        config = HomeServerConfig.load_config("", ["-c", self.file])
+        self.assertTrue(
+            hasattr(config, "macaroon_secret_key"),
+            "Want config to have attr macaroon_secret_key"
+        )
+        if len(config.macaroon_secret_key) < 5:
+            self.fail(
+                "Want macaroon secret key to be string of at least length 5,"
+                "was: %r" % (config.macaroon_secret_key,)
+            )
+
+    def test_load_succeeds_if_macaroon_secret_key_missing(self):
+        self.generate_config_and_remove_lines_containing("macaroon")
+        config1 = HomeServerConfig.load_config("", ["-c", self.file])
+        config2 = HomeServerConfig.load_config("", ["-c", self.file])
+        self.assertEqual(config1.macaroon_secret_key, config2.macaroon_secret_key)
+
+    def generate_config(self):
+        HomeServerConfig.load_config("", [
+            "--generate-config",
+            "-c", self.file,
+            "--report-stats=yes",
+            "-H", "lemurs.win"
+        ])
+
+    def generate_config_and_remove_lines_containing(self, needle):
+        self.generate_config()
+
+        with open(self.file, "r") as f:
+            contents = f.readlines()
+        contents = [l for l in contents if needle not in l]
+        with open(self.file, "w") as f:
+            f.write("".join(contents))
diff --git a/tests/crypto/__init__.py b/tests/crypto/__init__.py
index 9bff9ec169..d0e9399dda 100644
--- a/tests/crypto/__init__.py
+++ b/tests/crypto/__init__.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2014 OpenMarket Ltd
+# Copyright 2014-2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/tests/crypto/test_event_signing.py b/tests/crypto/test_event_signing.py
index 7913472941..47cb328a01 100644
--- a/tests/crypto/test_event_signing.py
+++ b/tests/crypto/test_event_signing.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2015 OpenMarket Ltd
+# Copyright 2015, 2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/tests/events/test_utils.py b/tests/events/test_utils.py
index 16179921f0..894d0c3845 100644
--- a/tests/events/test_utils.py
+++ b/tests/events/test_utils.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2015 OpenMarket Ltd
+# Copyright 2015, 2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the 'License');
 # you may not use this file except in compliance with the License.
diff --git a/tests/federation/__init__.py b/tests/federation/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
--- a/tests/federation/__init__.py
+++ /dev/null
diff --git a/tests/federation/test_federation.py b/tests/federation/test_federation.py
deleted file mode 100644
index 96570f9072..0000000000
--- a/tests/federation/test_federation.py
+++ /dev/null
@@ -1,303 +0,0 @@
-# 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.
-
-# trial imports
-from twisted.internet import defer
-from tests import unittest
-
-# python imports
-from mock import Mock, ANY
-
-from ..utils import MockHttpResource, MockClock, setup_test_homeserver
-
-from synapse.federation import initialize_http_replication
-from synapse.events import FrozenEvent
-
-
-def make_pdu(prev_pdus=[], **kwargs):
-    """Provide some default fields for making a PduTuple."""
-    pdu_fields = {
-        "state_key": None,
-        "prev_events": prev_pdus,
-    }
-    pdu_fields.update(kwargs)
-
-    return FrozenEvent(pdu_fields)
-
-
-class FederationTestCase(unittest.TestCase):
-    @defer.inlineCallbacks
-    def setUp(self):
-        self.mock_resource = MockHttpResource()
-        self.mock_http_client = Mock(spec=[
-            "get_json",
-            "put_json",
-        ])
-        self.mock_persistence = Mock(spec=[
-            "prep_send_transaction",
-            "delivered_txn",
-            "get_received_txn_response",
-            "set_received_txn_response",
-            "get_destination_retry_timings",
-            "get_auth_chain",
-        ])
-        self.mock_persistence.get_received_txn_response.return_value = (
-            defer.succeed(None)
-        )
-
-        retry_timings_res = {
-            "destination": "",
-            "retry_last_ts": 0,
-            "retry_interval": 0,
-        }
-        self.mock_persistence.get_destination_retry_timings.return_value = (
-            defer.succeed(retry_timings_res)
-        )
-        self.mock_persistence.get_auth_chain.return_value = []
-        self.clock = MockClock()
-        hs = yield setup_test_homeserver(
-            resource_for_federation=self.mock_resource,
-            http_client=self.mock_http_client,
-            datastore=self.mock_persistence,
-            clock=self.clock,
-            keyring=Mock(),
-        )
-        self.federation = initialize_http_replication(hs)
-        self.distributor = hs.get_distributor()
-
-    @defer.inlineCallbacks
-    def test_get_state(self):
-        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
-        )
-        self.assertEquals(200, code)
-        self.assertFalse(response["pdus"])
-
-        # Now lets give the context some state
-        mock_handler.get_state_for_pdu.return_value = (
-            defer.succeed([
-                make_pdu(
-                    event_id="the-pdu-id",
-                    origin="red",
-                    user_id="@a:red",
-                    room_id="my-context",
-                    type="m.topic",
-                    origin_server_ts=123456789000,
-                    depth=1,
-                    content={"topic": "The topic"},
-                    state_key="",
-                    power_level=1000,
-                    prev_state="last-pdu-id",
-                ),
-            ])
-        )
-
-        (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):
-        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/event/abc123def456/",
-            None
-        )
-        self.assertEquals(404, code)
-
-        # Now insert such a PDU
-        mock_handler.get_persisted_pdu.return_value = (
-            defer.succeed(
-                make_pdu(
-                    event_id="abc123def456",
-                    origin="red",
-                    user_id="@a:red",
-                    room_id="my-context",
-                    type="m.text",
-                    origin_server_ts=123456789001,
-                    depth=1,
-                    content={"text": "Here is the message"},
-                )
-            )
-        )
-
-        (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]["type"])
-
-    @defer.inlineCallbacks
-    def test_send_pdu(self):
-        self.mock_http_client.put_json.return_value = defer.succeed(
-            (200, "OK")
-        )
-
-        pdu = make_pdu(
-            event_id="abc123def456",
-            origin="red",
-            user_id="@a:red",
-            room_id="my-context",
-            type="m.text",
-            origin_server_ts=123456789001,
-            depth=1,
-            content={"text": "Here is the message"},
-        )
-
-        yield self.federation.send_pdu(pdu, ["remote"])
-
-        self.mock_http_client.put_json.assert_called_with(
-            "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,
-            long_retries=True,
-        )
-
-    @defer.inlineCallbacks
-    def test_send_edu(self):
-        self.mock_http_client.put_json.return_value = defer.succeed(
-            (200, "OK")
-        )
-
-        yield self.federation.send_edu(
-            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": [
-                    {
-                        "edu_type": "m.test",
-                        "content": {"testing": "content here"},
-                    }
-                ],
-                'pdu_failures': [],
-            },
-            json_data_callback=ANY,
-            long_retries=True,
-        )
-
-    @defer.inlineCallbacks
-    def test_recv_edu(self):
-        recv_observer = Mock()
-        recv_observer.return_value = defer.succeed(())
-
-        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"}
-                    }
-                ]
-            }"""
-        )
-
-        recv_observer.assert_called_with(
-            "remote", {"testing": "reply here"}
-        )
-
-    @defer.inlineCallbacks
-    def test_send_query(self):
-        self.mock_http_client.get_json.return_value = defer.succeed(
-            {"your": "response"}
-        )
-
-        response = yield self.federation.make_query(
-            destination="remote",
-            query_type="a-question",
-            args={"one": "1", "two": "2"},
-        )
-
-        self.assertEquals({"your": "response"}, response)
-
-        self.mock_http_client.get_json.assert_called_with(
-            destination="remote",
-            path="/_matrix/federation/v1/query/a-question",
-            args={"one": "1", "two": "2"},
-            retry_on_dns_fail=True,
-        )
-
-    @defer.inlineCallbacks
-    def test_recv_query(self):
-        recv_handler = Mock()
-        recv_handler.return_value = defer.succeed({"another": "response"})
-
-        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
-        )
-
-        self.assertEquals(200, code)
-        self.assertEquals({"another": "response"}, response)
-
-        recv_handler.assert_called_with(
-            {"three": "3", "four": "4"}
-        )
diff --git a/tests/handlers/test_appservice.py b/tests/handlers/test_appservice.py
index 9e95d1e532..ba6e2c640e 100644
--- a/tests/handlers/test_appservice.py
+++ b/tests/handlers/test_appservice.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2015 OpenMarket Ltd
+# Copyright 2015, 2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/tests/handlers/test_auth.py b/tests/handlers/test_auth.py
index 978e4d0d2e..2f21bf91e5 100644
--- a/tests/handlers/test_auth.py
+++ b/tests/handlers/test_auth.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2015 OpenMarket Ltd
+# Copyright 2015, 2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/tests/handlers/test_directory.py b/tests/handlers/test_directory.py
index 27306ba427..5d602c1531 100644
--- a/tests/handlers/test_directory.py
+++ b/tests/handlers/test_directory.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2014 OpenMarket Ltd
+# Copyright 2014-2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/tests/handlers/test_federation.py b/tests/handlers/test_federation.py
deleted file mode 100644
index d392c23015..0000000000
--- a/tests/handlers/test_federation.py
+++ /dev/null
@@ -1,130 +0,0 @@
-# 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 twisted.internet import defer
-from tests import unittest
-
-from synapse.api.constants import EventTypes
-from synapse.events import FrozenEvent
-from synapse.handlers.federation import FederationHandler
-
-from mock import NonCallableMock, ANY, Mock
-
-from ..utils import setup_test_homeserver
-
-
-class FederationTestCase(unittest.TestCase):
-
-    @defer.inlineCallbacks
-    def setUp(self):
-
-        self.state_handler = NonCallableMock(spec_set=[
-            "compute_event_context",
-        ])
-
-        self.auth = NonCallableMock(spec_set=[
-            "check",
-            "check_host_in_room",
-        ])
-
-        self.hostname = "test"
-        hs = yield setup_test_homeserver(
-            self.hostname,
-            datastore=NonCallableMock(spec_set=[
-                "persist_event",
-                "store_room",
-                "get_room",
-                "get_destination_retry_timings",
-                "set_destination_retry_timings",
-                "have_events",
-            ]),
-            resource_for_federation=NonCallableMock(),
-            http_client=NonCallableMock(spec_set=[]),
-            notifier=NonCallableMock(spec_set=["on_new_room_event"]),
-            handlers=NonCallableMock(spec_set=[
-                "room_member_handler",
-                "federation_handler",
-            ]),
-            auth=self.auth,
-            state_handler=self.state_handler,
-            keyring=Mock(),
-        )
-
-        self.datastore = hs.get_datastore()
-        self.handlers = hs.get_handlers()
-        self.notifier = hs.get_notifier()
-        self.hs = hs
-
-        self.handlers.federation_handler = FederationHandler(self.hs)
-
-    @defer.inlineCallbacks
-    def test_msg(self):
-        pdu = FrozenEvent({
-            "type": EventTypes.Message,
-            "room_id": "foo",
-            "content": {"msgtype": u"fooo"},
-            "origin_server_ts": 0,
-            "event_id": "$a:b",
-            "user_id":"@a:b",
-            "origin": "b",
-            "auth_events": [],
-            "hashes": {"sha256":"AcLrgtUIqqwaGoHhrEvYG1YLDIsVPYJdSRGhkp3jJp8"},
-        })
-
-        self.datastore.persist_event.return_value = defer.succeed((1,1))
-        self.datastore.get_room.return_value = defer.succeed(True)
-        self.auth.check_host_in_room.return_value = defer.succeed(True)
-
-        retry_timings_res = {
-            "destination": "",
-            "retry_last_ts": 0,
-            "retry_interval": 0,
-        }
-        self.datastore.get_destination_retry_timings.return_value = (
-            defer.succeed(retry_timings_res)
-        )
-
-        def have_events(event_ids):
-            return defer.succeed({})
-        self.datastore.have_events.side_effect = have_events
-
-        def annotate(ev, old_state=None, outlier=False):
-            context = Mock()
-            context.current_state = {}
-            context.auth_events = {}
-            return defer.succeed(context)
-        self.state_handler.compute_event_context.side_effect = annotate
-
-        yield self.handlers.federation_handler.on_receive_pdu(
-            "fo", pdu, False
-        )
-
-        self.datastore.persist_event.assert_called_once_with(
-            ANY,
-            is_new_state=True,
-            backfilled=False,
-            current_state=None,
-            context=ANY,
-        )
-
-        self.state_handler.compute_event_context.assert_called_once_with(
-            ANY, old_state=None, outlier=False
-        )
-
-        self.auth.check.assert_called_once_with(ANY, auth_events={})
-
-        self.notifier.on_new_room_event.assert_called_once_with(
-            ANY, 1, 1, extra_users=[]
-        )
diff --git a/tests/handlers/test_presence.py b/tests/handlers/test_presence.py
index c42b5b80d7..447a22b5fc 100644
--- a/tests/handlers/test_presence.py
+++ b/tests/handlers/test_presence.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2014 OpenMarket Ltd
+# Copyright 2014-2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -28,7 +28,6 @@ from synapse.api.constants import PresenceState
 from synapse.api.errors import SynapseError
 from synapse.handlers.presence import PresenceHandler, UserPresenceCache
 from synapse.streams.config import SourcePaginationConfig
-from synapse.storage.transactions import DestinationsTable
 from synapse.types import UserID
 
 OFFLINE = PresenceState.OFFLINE
diff --git a/tests/handlers/test_presencelike.py b/tests/handlers/test_presencelike.py
index 19107caeee..76f6ba5e7b 100644
--- a/tests/handlers/test_presencelike.py
+++ b/tests/handlers/test_presencelike.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2014 OpenMarket Ltd
+# Copyright 2014-2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/tests/handlers/test_profile.py b/tests/handlers/test_profile.py
index 31f03d73df..237fc8223c 100644
--- a/tests/handlers/test_profile.py
+++ b/tests/handlers/test_profile.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2014 OpenMarket Ltd
+# Copyright 2014-2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/tests/handlers/test_room.py b/tests/handlers/test_room.py
deleted file mode 100644
index 2a7553f982..0000000000
--- a/tests/handlers/test_room.py
+++ /dev/null
@@ -1,404 +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 twisted.internet import defer
-from .. import unittest
-
-from synapse.api.constants import EventTypes, Membership
-from synapse.handlers.room import RoomMemberHandler, RoomCreationHandler
-from synapse.handlers.profile import ProfileHandler
-from synapse.types import UserID
-from ..utils import setup_test_homeserver
-
-from mock import Mock, NonCallableMock
-
-
-class RoomMemberHandlerTestCase(unittest.TestCase):
-
-    @defer.inlineCallbacks
-    def setUp(self):
-        self.hostname = "red"
-        hs = yield setup_test_homeserver(
-            self.hostname,
-            ratelimiter=NonCallableMock(spec_set=[
-                "send_message",
-            ]),
-            datastore=NonCallableMock(spec_set=[
-                "persist_event",
-                "get_room_member",
-                "get_room",
-                "store_room",
-                "get_latest_events_in_room",
-                "add_event_hashes",
-            ]),
-            resource_for_federation=NonCallableMock(),
-            http_client=NonCallableMock(spec_set=[]),
-            notifier=NonCallableMock(spec_set=["on_new_room_event"]),
-            handlers=NonCallableMock(spec_set=[
-                "room_member_handler",
-                "profile_handler",
-                "federation_handler",
-            ]),
-            auth=NonCallableMock(spec_set=[
-                "check",
-                "add_auth_events",
-                "check_host_in_room",
-            ]),
-            state_handler=NonCallableMock(spec_set=[
-                "compute_event_context",
-                "get_current_state",
-            ]),
-        )
-
-        self.federation = NonCallableMock(spec_set=[
-            "handle_new_event",
-            "send_invite",
-            "get_state_for_room",
-        ])
-
-        self.datastore = hs.get_datastore()
-        self.handlers = hs.get_handlers()
-        self.notifier = hs.get_notifier()
-        self.state_handler = hs.get_state_handler()
-        self.distributor = hs.get_distributor()
-        self.auth = hs.get_auth()
-        self.hs = hs
-
-        self.handlers.federation_handler = self.federation
-
-        self.distributor.declare("collect_presencelike_data")
-
-        self.handlers.room_member_handler = RoomMemberHandler(self.hs)
-        self.handlers.profile_handler = ProfileHandler(self.hs)
-        self.room_member_handler = self.handlers.room_member_handler
-
-        self.ratelimiter = hs.get_ratelimiter()
-        self.ratelimiter.send_message.return_value = (True, 0)
-
-        self.datastore.persist_event.return_value = (1,1)
-        self.datastore.add_event_hashes.return_value = []
-
-    @defer.inlineCallbacks
-    def test_invite(self):
-        room_id = "!foo:red"
-        user_id = "@bob:red"
-        target_user_id = "@red:blue"
-        content = {"membership": Membership.INVITE}
-
-        builder = self.hs.get_event_builder_factory().new({
-            "type": EventTypes.Member,
-            "sender": user_id,
-            "state_key": target_user_id,
-            "room_id": room_id,
-            "content": content,
-        })
-
-        self.datastore.get_latest_events_in_room.return_value = (
-            defer.succeed([])
-        )
-
-        def annotate(_):
-            ctx = Mock()
-            ctx.current_state = {
-                (EventTypes.Member, "@alice:green"): self._create_member(
-                    user_id="@alice:green",
-                    room_id=room_id,
-                ),
-                (EventTypes.Member, "@bob:red"): self._create_member(
-                    user_id="@bob:red",
-                    room_id=room_id,
-                ),
-            }
-            ctx.prev_state_events = []
-
-            return defer.succeed(ctx)
-
-        self.state_handler.compute_event_context.side_effect = annotate
-
-        def add_auth(_, ctx):
-            ctx.auth_events = ctx.current_state[
-                (EventTypes.Member, "@bob:red")
-            ]
-
-            return defer.succeed(True)
-        self.auth.add_auth_events.side_effect = add_auth
-
-        def send_invite(domain, event):
-            return defer.succeed(event)
-
-        self.federation.send_invite.side_effect = send_invite
-
-        room_handler = self.room_member_handler
-        event, context = yield room_handler._create_new_client_event(
-            builder
-        )
-
-        yield room_handler.change_membership(event, context)
-
-        self.state_handler.compute_event_context.assert_called_once_with(
-            builder
-        )
-
-        self.auth.add_auth_events.assert_called_once_with(
-            builder, context
-        )
-
-        self.federation.send_invite.assert_called_once_with(
-            "blue", event,
-        )
-
-        self.datastore.persist_event.assert_called_once_with(
-            event, context=context,
-        )
-        self.notifier.on_new_room_event.assert_called_once_with(
-            event, 1, 1, extra_users=[UserID.from_string(target_user_id)]
-        )
-        self.assertFalse(self.datastore.get_room.called)
-        self.assertFalse(self.datastore.store_room.called)
-        self.assertFalse(self.federation.get_state_for_room.called)
-
-    @defer.inlineCallbacks
-    def test_simple_join(self):
-        room_id = "!foo:red"
-        user_id = "@bob:red"
-        user = UserID.from_string(user_id)
-
-        join_signal_observer = Mock()
-        self.distributor.observe("user_joined_room", join_signal_observer)
-
-        builder = self.hs.get_event_builder_factory().new({
-            "type": EventTypes.Member,
-            "sender": user_id,
-            "state_key": user_id,
-            "room_id": room_id,
-            "content": {"membership": Membership.JOIN},
-        })
-
-        self.datastore.get_latest_events_in_room.return_value = (
-            defer.succeed([])
-        )
-
-        def annotate(_):
-            ctx = Mock()
-            ctx.current_state = {
-                (EventTypes.Member, "@bob:red"): self._create_member(
-                    user_id="@bob:red",
-                    room_id=room_id,
-                    membership=Membership.INVITE
-                ),
-            }
-            ctx.prev_state_events = []
-
-            return defer.succeed(ctx)
-
-        self.state_handler.compute_event_context.side_effect = annotate
-
-        def add_auth(_, ctx):
-            ctx.auth_events = ctx.current_state[
-                (EventTypes.Member, "@bob:red")
-            ]
-
-            return defer.succeed(True)
-        self.auth.add_auth_events.side_effect = add_auth
-
-        room_handler = self.room_member_handler
-        event, context = yield room_handler._create_new_client_event(
-            builder
-        )
-
-        # Actual invocation
-        yield room_handler.change_membership(event, context)
-
-        self.federation.handle_new_event.assert_called_once_with(
-            event, destinations=set()
-        )
-
-        self.datastore.persist_event.assert_called_once_with(
-            event, context=context
-        )
-        self.notifier.on_new_room_event.assert_called_once_with(
-            event, 1, 1, extra_users=[user]
-        )
-
-        join_signal_observer.assert_called_with(
-            user=user, room_id=room_id
-        )
-
-    def _create_member(self, user_id, room_id, membership=Membership.JOIN):
-        builder = self.hs.get_event_builder_factory().new({
-            "type": EventTypes.Member,
-            "sender": user_id,
-            "state_key": user_id,
-            "room_id": room_id,
-            "content": {"membership": membership},
-        })
-
-        return builder.build()
-
-    @defer.inlineCallbacks
-    def test_simple_leave(self):
-        room_id = "!foo:red"
-        user_id = "@bob:red"
-        user = UserID.from_string(user_id)
-
-        builder = self.hs.get_event_builder_factory().new({
-            "type": EventTypes.Member,
-            "sender": user_id,
-            "state_key": user_id,
-            "room_id": room_id,
-            "content": {"membership": Membership.LEAVE},
-        })
-
-        self.datastore.get_latest_events_in_room.return_value = (
-            defer.succeed([])
-        )
-
-        def annotate(_):
-            ctx = Mock()
-            ctx.current_state = {
-                (EventTypes.Member, "@bob:red"): self._create_member(
-                    user_id="@bob:red",
-                    room_id=room_id,
-                    membership=Membership.JOIN
-                ),
-            }
-            ctx.prev_state_events = []
-
-            return defer.succeed(ctx)
-
-        self.state_handler.compute_event_context.side_effect = annotate
-
-        def add_auth(_, ctx):
-            ctx.auth_events = ctx.current_state[
-                (EventTypes.Member, "@bob:red")
-            ]
-
-            return defer.succeed(True)
-        self.auth.add_auth_events.side_effect = add_auth
-
-        room_handler = self.room_member_handler
-        event, context = yield room_handler._create_new_client_event(
-            builder
-        )
-
-        leave_signal_observer = Mock()
-        self.distributor.observe("user_left_room", leave_signal_observer)
-
-        # Actual invocation
-        yield room_handler.change_membership(event, context)
-
-        self.federation.handle_new_event.assert_called_once_with(
-            event, destinations=set(['red'])
-        )
-
-        self.datastore.persist_event.assert_called_once_with(
-            event, context=context
-        )
-        self.notifier.on_new_room_event.assert_called_once_with(
-            event, 1, 1, extra_users=[user]
-        )
-
-        leave_signal_observer.assert_called_with(
-            user=user, room_id=room_id
-        )
-
-
-class RoomCreationTest(unittest.TestCase):
-
-    @defer.inlineCallbacks
-    def setUp(self):
-        self.hostname = "red"
-
-        hs = yield setup_test_homeserver(
-            self.hostname,
-            datastore=NonCallableMock(spec_set=[
-                "store_room",
-                "snapshot_room",
-                "persist_event",
-                "get_joined_hosts_for_room",
-            ]),
-            http_client=NonCallableMock(spec_set=[]),
-            notifier=NonCallableMock(spec_set=["on_new_room_event"]),
-            handlers=NonCallableMock(spec_set=[
-                "room_creation_handler",
-                "message_handler",
-            ]),
-            auth=NonCallableMock(spec_set=["check", "add_auth_events"]),
-            ratelimiter=NonCallableMock(spec_set=[
-                "send_message",
-            ]),
-        )
-
-        self.federation = NonCallableMock(spec_set=[
-            "handle_new_event",
-        ])
-
-        self.handlers = hs.get_handlers()
-
-        self.handlers.room_creation_handler = RoomCreationHandler(hs)
-        self.room_creation_handler = self.handlers.room_creation_handler
-
-        self.message_handler = self.handlers.message_handler
-
-        self.ratelimiter = hs.get_ratelimiter()
-        self.ratelimiter.send_message.return_value = (True, 0)
-
-    @defer.inlineCallbacks
-    def test_room_creation(self):
-        user_id = "@foo:red"
-        room_id = "!bobs_room:red"
-        config = {"visibility": "private"}
-
-        yield self.room_creation_handler.create_room(
-            user_id=user_id,
-            room_id=room_id,
-            config=config,
-        )
-
-        self.assertTrue(self.message_handler.create_and_send_event.called)
-
-        event_dicts = [
-            e[0][0]
-            for e in self.message_handler.create_and_send_event.call_args_list
-        ]
-
-        self.assertTrue(len(event_dicts) > 3)
-
-        self.assertDictContainsSubset(
-            {
-                "type": EventTypes.Create,
-                "sender": user_id,
-                "room_id": room_id,
-            },
-            event_dicts[0]
-        )
-
-        self.assertEqual(user_id, event_dicts[0]["content"]["creator"])
-
-        self.assertDictContainsSubset(
-            {
-                "type": EventTypes.Member,
-                "sender": user_id,
-                "room_id": room_id,
-                "state_key": user_id,
-            },
-            event_dicts[1]
-        )
-
-        self.assertEqual(
-            Membership.JOIN,
-            event_dicts[1]["content"]["membership"]
-        )
diff --git a/tests/handlers/test_typing.py b/tests/handlers/test_typing.py
index 5b1feeb45b..763c04d667 100644
--- a/tests/handlers/test_typing.py
+++ b/tests/handlers/test_typing.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2014 OpenMarket Ltd
+# Copyright 2014-2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -27,7 +27,6 @@ from ..utils import (
 from synapse.api.errors import AuthError
 from synapse.handlers.typing import TypingNotificationHandler
 
-from synapse.storage.transactions import DestinationsTable
 from synapse.types import UserID
 
 
diff --git a/tests/metrics/test_metric.py b/tests/metrics/test_metric.py
index 6009014297..f9e5e5af01 100644
--- a/tests/metrics/test_metric.py
+++ b/tests/metrics/test_metric.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2015 OpenMarket Ltd
+# Copyright 2015, 2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/tests/rest/__init__.py b/tests/rest/__init__.py
index 1a84d94cd9..fe0ac3f8e9 100644
--- a/tests/rest/__init__.py
+++ b/tests/rest/__init__.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2015 OpenMarket Ltd
+# Copyright 2015, 2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/tests/rest/client/__init__.py b/tests/rest/client/__init__.py
index 1a84d94cd9..fe0ac3f8e9 100644
--- a/tests/rest/client/__init__.py
+++ b/tests/rest/client/__init__.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2015 OpenMarket Ltd
+# Copyright 2015, 2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/tests/rest/client/v1/__init__.py b/tests/rest/client/v1/__init__.py
index 9bff9ec169..d0e9399dda 100644
--- a/tests/rest/client/v1/__init__.py
+++ b/tests/rest/client/v1/__init__.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2014 OpenMarket Ltd
+# Copyright 2014-2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/tests/rest/client/v1/test_events.py b/tests/rest/client/v1/test_events.py
index ac3b0b58ac..e9698bfdc9 100644
--- a/tests/rest/client/v1/test_events.py
+++ b/tests/rest/client/v1/test_events.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2014 OpenMarket Ltd
+# Copyright 2014-2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -122,7 +122,7 @@ class EventStreamPermissionsTestCase(RestTestCase):
         self.ratelimiter = hs.get_ratelimiter()
         self.ratelimiter.send_message.return_value = (True, 0)
         hs.config.enable_registration_captcha = False
-        hs.config.disable_registration = False
+        hs.config.enable_registration = True
 
         hs.get_handlers().federation_handler = Mock()
 
diff --git a/tests/rest/client/v1/test_presence.py b/tests/rest/client/v1/test_presence.py
index 8581796f72..8d7cfd79ab 100644
--- a/tests/rest/client/v1/test_presence.py
+++ b/tests/rest/client/v1/test_presence.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2014 OpenMarket Ltd
+# Copyright 2014-2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -14,7 +14,6 @@
 # limitations under the License.
 
 """Tests REST events for /presence paths."""
-
 from tests import unittest
 from twisted.internet import defer
 
@@ -26,7 +25,7 @@ from synapse.api.constants import PresenceState
 from synapse.handlers.presence import PresenceHandler
 from synapse.rest.client.v1 import presence
 from synapse.rest.client.v1 import events
-from synapse.types import UserID
+from synapse.types import Requester, UserID
 from synapse.util.async import run_on_reactor
 
 from collections import namedtuple
@@ -281,6 +280,15 @@ class PresenceEventStreamTestCase(unittest.TestCase):
         }
         EventSources.SOURCE_TYPES["presence"] = PresenceEventSource
 
+        clock = Mock(spec=[
+            "call_later",
+            "cancel_call_later",
+            "time_msec",
+            "looping_call",
+        ])
+
+        clock.time_msec.return_value = 1000000
+
         hs = yield setup_test_homeserver(
             http_client=None,
             resource_for_client=self.mock_resource,
@@ -290,18 +298,11 @@ class PresenceEventStreamTestCase(unittest.TestCase):
                 "get_presence_list",
                 "get_rooms_for_user",
             ]),
-            clock=Mock(spec=[
-                "call_later",
-                "cancel_call_later",
-                "time_msec",
-                "looping_call",
-            ]),
+            clock=clock,
         )
 
-        hs.get_clock().time_msec.return_value = 1000000
-
         def _get_user_by_req(req=None, allow_guest=False):
-            return (UserID.from_string(myid), "", False)
+            return Requester(UserID.from_string(myid), "", False)
 
         hs.get_v1auth().get_user_by_req = _get_user_by_req
 
diff --git a/tests/rest/client/v1/test_profile.py b/tests/rest/client/v1/test_profile.py
index adcc1d1969..c1a3f52043 100644
--- a/tests/rest/client/v1/test_profile.py
+++ b/tests/rest/client/v1/test_profile.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2014 OpenMarket Ltd
+# Copyright 2014-2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -14,16 +14,15 @@
 # limitations under the License.
 
 """Tests REST events for /profile paths."""
-
 from tests import unittest
 from twisted.internet import defer
 
-from mock import Mock, NonCallableMock
+from mock import Mock
 
 from ....utils import MockHttpResource, setup_test_homeserver
 
 from synapse.api.errors import SynapseError, AuthError
-from synapse.types import UserID
+from synapse.types import Requester, UserID
 
 from synapse.rest.client.v1 import profile
 
@@ -53,7 +52,7 @@ class ProfileTestCase(unittest.TestCase):
         )
 
         def _get_user_by_req(request=None, allow_guest=False):
-            return (UserID.from_string(myid), "", False)
+            return Requester(UserID.from_string(myid), "", False)
 
         hs.get_v1auth().get_user_by_req = _get_user_by_req
 
diff --git a/tests/rest/client/v1/test_rooms.py b/tests/rest/client/v1/test_rooms.py
index 7749378064..ad5dd3bd6e 100644
--- a/tests/rest/client/v1/test_rooms.py
+++ b/tests/rest/client/v1/test_rooms.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2014 OpenMarket Ltd
+# Copyright 2014-2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -1045,8 +1045,13 @@ class RoomMessageListTestCase(RestTestCase):
         self.assertTrue("end" in response)
 
     @defer.inlineCallbacks
-    def test_stream_token_is_rejected(self):
+    def test_stream_token_is_accepted_for_fwd_pagianation(self):
+        token = "s0_0_0_0_0"
         (code, response) = yield self.mock_resource.trigger_get(
-            "/rooms/%s/messages?access_token=x&from=s0_0_0_0" %
-            self.room_id)
-        self.assertEquals(400, code)
+            "/rooms/%s/messages?access_token=x&from=%s" %
+            (self.room_id, token))
+        self.assertEquals(200, code)
+        self.assertTrue("start" in response)
+        self.assertEquals(token, response['start'])
+        self.assertTrue("chunk" in response)
+        self.assertTrue("end" in response)
diff --git a/tests/rest/client/v1/test_typing.py b/tests/rest/client/v1/test_typing.py
index 61b9cc743b..c4ac181a33 100644
--- a/tests/rest/client/v1/test_typing.py
+++ b/tests/rest/client/v1/test_typing.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2014 OpenMarket Ltd
+# Copyright 2014-2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/tests/rest/client/v1/utils.py b/tests/rest/client/v1/utils.py
index 85096a0326..af376804f6 100644
--- a/tests/rest/client/v1/utils.py
+++ b/tests/rest/client/v1/utils.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2014 OpenMarket Ltd
+# Copyright 2014-2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/tests/rest/client/v2_alpha/__init__.py b/tests/rest/client/v2_alpha/__init__.py
index fa9e17ec4f..16dce6c723 100644
--- a/tests/rest/client/v2_alpha/__init__.py
+++ b/tests/rest/client/v2_alpha/__init__.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2015 OpenMarket Ltd
+# Copyright 2015, 2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/tests/rest/client/v2_alpha/test_filter.py b/tests/rest/client/v2_alpha/test_filter.py
index 80ddabf818..c86e904c8e 100644
--- a/tests/rest/client/v2_alpha/test_filter.py
+++ b/tests/rest/client/v2_alpha/test_filter.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2015 OpenMarket Ltd
+# Copyright 2015, 2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/tests/rest/client/v2_alpha/test_register.py b/tests/rest/client/v2_alpha/test_register.py
index f9a2b22485..df0841b0b1 100644
--- a/tests/rest/client/v2_alpha/test_register.py
+++ b/tests/rest/client/v2_alpha/test_register.py
@@ -41,7 +41,7 @@ class RegisterRestServletTestCase(unittest.TestCase):
         self.hs.hostname = "superbig~testing~thing.com"
         self.hs.get_auth = Mock(return_value=self.auth)
         self.hs.get_handlers = Mock(return_value=self.handlers)
-        self.hs.config.disable_registration = False
+        self.hs.config.enable_registration = True
 
         # init the thing we're testing
         self.servlet = RegisterRestServlet(self.hs)
@@ -120,7 +120,7 @@ class RegisterRestServletTestCase(unittest.TestCase):
         }))
 
     def test_POST_disabled_registration(self):
-        self.hs.config.disable_registration = True
+        self.hs.config.enable_registration = False
         self.request_data = json.dumps({
             "username": "kermit",
             "password": "monkey"
diff --git a/tests/storage/event_injector.py b/tests/storage/event_injector.py
index 42bd8928bd..dca785eb27 100644
--- a/tests/storage/event_injector.py
+++ b/tests/storage/event_injector.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2015 OpenMarket Ltd
+# Copyright 2015, 2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/tests/storage/test__base.py b/tests/storage/test__base.py
index e72cace8ff..219288621d 100644
--- a/tests/storage/test__base.py
+++ b/tests/storage/test__base.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2015 OpenMarket Ltd
+# Copyright 2015, 2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/tests/storage/test_appservice.py b/tests/storage/test_appservice.py
index 77376b348e..ed8af10d87 100644
--- a/tests/storage/test_appservice.py
+++ b/tests/storage/test_appservice.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2015 OpenMarket Ltd
+# Copyright 2015, 2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -12,12 +12,13 @@
 # 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.
+import tempfile
+from synapse.config._base import ConfigError
 from tests import unittest
 from twisted.internet import defer
 
 from tests.utils import setup_test_homeserver
 from synapse.appservice import ApplicationService, ApplicationServiceState
-from synapse.server import HomeServer
 from synapse.storage.appservice import (
     ApplicationServiceStore, ApplicationServiceTransactionStore
 )
@@ -26,7 +27,6 @@ import json
 import os
 import yaml
 from mock import Mock
-from tests.utils import SQLiteMemoryDbPool, MockClock
 
 
 class ApplicationServiceStoreTestCase(unittest.TestCase):
@@ -41,9 +41,16 @@ class ApplicationServiceStoreTestCase(unittest.TestCase):
 
         self.as_token = "token1"
         self.as_url = "some_url"
-        self._add_appservice(self.as_token, self.as_url, "some_hs_token", "bob")
-        self._add_appservice("token2", "some_url", "some_hs_token", "bob")
-        self._add_appservice("token3", "some_url", "some_hs_token", "bob")
+        self.as_id = "as1"
+        self._add_appservice(
+            self.as_token,
+            self.as_id,
+            self.as_url,
+            "some_hs_token",
+            "bob"
+        )
+        self._add_appservice("token2", "as2", "some_url", "some_hs_token", "bob")
+        self._add_appservice("token3", "as3", "some_url", "some_hs_token", "bob")
         # must be done after inserts
         self.store = ApplicationServiceStore(hs)
 
@@ -55,9 +62,9 @@ class ApplicationServiceStoreTestCase(unittest.TestCase):
             except:
                 pass
 
-    def _add_appservice(self, as_token, url, hs_token, sender):
+    def _add_appservice(self, as_token, id, url, hs_token, sender):
         as_yaml = dict(url=url, as_token=as_token, hs_token=hs_token,
-                       sender_localpart=sender, namespaces={})
+                       id=id, sender_localpart=sender, namespaces={})
         # use the token as the filename
         with open(as_token, 'w') as outfile:
             outfile.write(yaml.dump(as_yaml))
@@ -74,6 +81,7 @@ class ApplicationServiceStoreTestCase(unittest.TestCase):
             self.as_token
         )
         self.assertEquals(stored_service.token, self.as_token)
+        self.assertEquals(stored_service.id, self.as_id)
         self.assertEquals(stored_service.url, self.as_url)
         self.assertEquals(
             stored_service.namespaces[ApplicationService.NS_ALIASES],
@@ -110,34 +118,34 @@ class ApplicationServiceTransactionStoreTestCase(unittest.TestCase):
             {
                 "token": "token1",
                 "url": "https://matrix-as.org",
-                "id": "token1"
+                "id": "id_1"
             },
             {
                 "token": "alpha_tok",
                 "url": "https://alpha.com",
-                "id": "alpha_tok"
+                "id": "id_alpha"
             },
             {
                 "token": "beta_tok",
                 "url": "https://beta.com",
-                "id": "beta_tok"
+                "id": "id_beta"
             },
             {
-                "token": "delta_tok",
-                "url": "https://delta.com",
-                "id": "delta_tok"
+                "token": "gamma_tok",
+                "url": "https://gamma.com",
+                "id": "id_gamma"
             },
         ]
         for s in self.as_list:
-            yield self._add_service(s["url"], s["token"])
+            yield self._add_service(s["url"], s["token"], s["id"])
 
         self.as_yaml_files = []
 
         self.store = TestTransactionStore(hs)
 
-    def _add_service(self, url, as_token):
+    def _add_service(self, url, as_token, id):
         as_yaml = dict(url=url, as_token=as_token, hs_token="something",
-                       sender_localpart="a_sender", namespaces={})
+                       id=id, sender_localpart="a_sender", namespaces={})
         # use the token as the filename
         with open(as_token, 'w') as outfile:
             outfile.write(yaml.dump(as_yaml))
@@ -405,3 +413,64 @@ class TestTransactionStore(ApplicationServiceTransactionStore,
 
     def __init__(self, hs):
         super(TestTransactionStore, self).__init__(hs)
+
+
+class ApplicationServiceStoreConfigTestCase(unittest.TestCase):
+
+    def _write_config(self, suffix, **kwargs):
+        vals = {
+            "id": "id" + suffix,
+            "url": "url" + suffix,
+            "as_token": "as_token" + suffix,
+            "hs_token": "hs_token" + suffix,
+            "sender_localpart": "sender_localpart" + suffix,
+            "namespaces": {},
+        }
+        vals.update(kwargs)
+
+        _, path = tempfile.mkstemp(prefix="as_config")
+        with open(path, "w") as f:
+            f.write(yaml.dump(vals))
+        return path
+
+    @defer.inlineCallbacks
+    def test_unique_works(self):
+        f1 = self._write_config(suffix="1")
+        f2 = self._write_config(suffix="2")
+
+        config = Mock(app_service_config_files=[f1, f2])
+        hs = yield setup_test_homeserver(config=config, datastore=Mock())
+
+        ApplicationServiceStore(hs)
+
+    @defer.inlineCallbacks
+    def test_duplicate_ids(self):
+        f1 = self._write_config(id="id", suffix="1")
+        f2 = self._write_config(id="id", suffix="2")
+
+        config = Mock(app_service_config_files=[f1, f2])
+        hs = yield setup_test_homeserver(config=config, datastore=Mock())
+
+        with self.assertRaises(ConfigError) as cm:
+            ApplicationServiceStore(hs)
+
+        e = cm.exception
+        self.assertIn(f1, e.message)
+        self.assertIn(f2, e.message)
+        self.assertIn("id", e.message)
+
+    @defer.inlineCallbacks
+    def test_duplicate_as_tokens(self):
+        f1 = self._write_config(as_token="as_token", suffix="1")
+        f2 = self._write_config(as_token="as_token", suffix="2")
+
+        config = Mock(app_service_config_files=[f1, f2])
+        hs = yield setup_test_homeserver(config=config, datastore=Mock())
+
+        with self.assertRaises(ConfigError) as cm:
+            ApplicationServiceStore(hs)
+
+        e = cm.exception
+        self.assertIn(f1, e.message)
+        self.assertIn(f2, e.message)
+        self.assertIn("as_token", e.message)
diff --git a/tests/storage/test_base.py b/tests/storage/test_base.py
index 1ddca1da4c..152d027663 100644
--- a/tests/storage/test_base.py
+++ b/tests/storage/test_base.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2014 OpenMarket Ltd
+# Copyright 2014-2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/tests/storage/test_directory.py b/tests/storage/test_directory.py
index b9bfbc00e2..b087892e0b 100644
--- a/tests/storage/test_directory.py
+++ b/tests/storage/test_directory.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2014 OpenMarket Ltd
+# Copyright 2014-2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/tests/storage/test_events.py b/tests/storage/test_events.py
index 946cd3e9f2..4aa82d4c9d 100644
--- a/tests/storage/test_events.py
+++ b/tests/storage/test_events.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2015 OpenMarket Ltd
+# Copyright 2015, 2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/tests/storage/test_presence.py b/tests/storage/test_presence.py
index 065eebdbcf..333f1e10f1 100644
--- a/tests/storage/test_presence.py
+++ b/tests/storage/test_presence.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2014 OpenMarket Ltd
+# Copyright 2014-2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/tests/storage/test_profile.py b/tests/storage/test_profile.py
index 1fa783f313..47e2768b2c 100644
--- a/tests/storage/test_profile.py
+++ b/tests/storage/test_profile.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2014 OpenMarket Ltd
+# Copyright 2014-2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/tests/storage/test_redaction.py b/tests/storage/test_redaction.py
index dbf9700e6a..5880409867 100644
--- a/tests/storage/test_redaction.py
+++ b/tests/storage/test_redaction.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2014 OpenMarket Ltd
+# Copyright 2014-2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/tests/storage/test_registration.py b/tests/storage/test_registration.py
index 0cce6c37df..7b3b4c13bc 100644
--- a/tests/storage/test_registration.py
+++ b/tests/storage/test_registration.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2014 OpenMarket Ltd
+# Copyright 2014-2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -18,7 +18,6 @@ from tests import unittest
 from twisted.internet import defer
 
 from synapse.api.errors import StoreError
-from synapse.storage.registration import RegistrationStore
 from synapse.util import stringutils
 
 from tests.utils import setup_test_homeserver
@@ -31,7 +30,7 @@ class RegistrationStoreTestCase(unittest.TestCase):
         hs = yield setup_test_homeserver()
         self.db_pool = hs.get_db_pool()
 
-        self.store = RegistrationStore(hs)
+        self.store = hs.get_datastore()
 
         self.user_id = "@my-user:test"
         self.tokens = ["AbCdEfGhIjKlMnOpQrStUvWxYz",
@@ -45,7 +44,7 @@ class RegistrationStoreTestCase(unittest.TestCase):
         self.assertEquals(
             # TODO(paul): Surely this field should be 'user_id', not 'name'
             #  Additionally surely it shouldn't come in a 1-element list
-            {"name": self.user_id, "password_hash": self.pwhash},
+            {"name": self.user_id, "password_hash": self.pwhash, "is_guest": 0},
             (yield self.store.get_user_by_id(self.user_id))
         )
 
diff --git a/tests/storage/test_room.py b/tests/storage/test_room.py
index 91c967548d..0baaf3df21 100644
--- a/tests/storage/test_room.py
+++ b/tests/storage/test_room.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2014 OpenMarket Ltd
+# Copyright 2014-2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -51,32 +51,6 @@ class RoomStoreTestCase(unittest.TestCase):
             (yield self.store.get_room(self.room.to_string()))
         )
 
-    @defer.inlineCallbacks
-    def test_get_rooms(self):
-        # get_rooms does an INNER JOIN on the room_aliases table :(
-
-        rooms = yield self.store.get_rooms(is_public=True)
-        # Should be empty before we add the alias
-        self.assertEquals([], rooms)
-
-        yield self.store.create_room_alias_association(
-            room_alias=self.alias,
-            room_id=self.room.to_string(),
-            servers=["test"]
-        )
-
-        rooms = yield self.store.get_rooms(is_public=True)
-
-        self.assertEquals(1, len(rooms))
-        self.assertEquals({
-            "name": None,
-            "room_id": self.room.to_string(),
-            "topic": None,
-            "aliases": [self.alias.to_string()],
-            "world_readable": False,
-            "guest_can_join": False,
-        }, rooms[0])
-
 
 class RoomEventsStoreTestCase(unittest.TestCase):
 
diff --git a/tests/storage/test_roommember.py b/tests/storage/test_roommember.py
index 785953cc89..bab15c4165 100644
--- a/tests/storage/test_roommember.py
+++ b/tests/storage/test_roommember.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2014 OpenMarket Ltd
+# Copyright 2014-2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/tests/storage/test_stream.py b/tests/storage/test_stream.py
index e5c2c5cc8e..708208aff1 100644
--- a/tests/storage/test_stream.py
+++ b/tests/storage/test_stream.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2014 OpenMarket Ltd
+# Copyright 2014-2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/tests/test_distributor.py b/tests/test_distributor.py
index 8ed48cfb70..a80f580ba6 100644
--- a/tests/test_distributor.py
+++ b/tests/test_distributor.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2014 OpenMarket Ltd
+# Copyright 2014-2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/tests/test_dns.py b/tests/test_dns.py
new file mode 100644
index 0000000000..637b1606f8
--- /dev/null
+++ b/tests/test_dns.py
@@ -0,0 +1,115 @@
+# -*- coding: utf-8 -*-
+# Copyright 2014-2016 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 . import unittest
+from twisted.internet import defer
+from twisted.names import dns, error
+
+from mock import Mock
+
+from synapse.http.endpoint import resolve_service
+
+
+class DnsTestCase(unittest.TestCase):
+
+    @defer.inlineCallbacks
+    def test_resolve(self):
+        dns_client_mock = Mock()
+
+        service_name = "test_service.examle.com"
+        host_name = "example.com"
+        ip_address = "127.0.0.1"
+
+        answer_srv = dns.RRHeader(
+            type=dns.SRV,
+            payload=dns.Record_SRV(
+                target=host_name,
+            )
+        )
+
+        answer_a = dns.RRHeader(
+            type=dns.A,
+            payload=dns.Record_A(
+                address=ip_address,
+            )
+        )
+
+        dns_client_mock.lookupService.return_value = ([answer_srv], None, None)
+        dns_client_mock.lookupAddress.return_value = ([answer_a], None, None)
+
+        cache = {}
+
+        servers = yield resolve_service(
+            service_name, dns_client=dns_client_mock, cache=cache
+        )
+
+        dns_client_mock.lookupService.assert_called_once_with(service_name)
+        dns_client_mock.lookupAddress.assert_called_once_with(host_name)
+
+        self.assertEquals(len(servers), 1)
+        self.assertEquals(servers, cache[service_name])
+        self.assertEquals(servers[0].host, ip_address)
+
+    @defer.inlineCallbacks
+    def test_from_cache(self):
+        dns_client_mock = Mock()
+        dns_client_mock.lookupService.return_value = defer.fail(error.DNSServerError())
+
+        service_name = "test_service.examle.com"
+
+        cache = {
+            service_name: [object()]
+        }
+
+        servers = yield resolve_service(
+            service_name, dns_client=dns_client_mock, cache=cache
+        )
+
+        dns_client_mock.lookupService.assert_called_once_with(service_name)
+
+        self.assertEquals(len(servers), 1)
+        self.assertEquals(servers, cache[service_name])
+
+    @defer.inlineCallbacks
+    def test_empty_cache(self):
+        dns_client_mock = Mock()
+
+        dns_client_mock.lookupService.return_value = defer.fail(error.DNSServerError())
+
+        service_name = "test_service.examle.com"
+
+        cache = {}
+
+        with self.assertRaises(error.DNSServerError):
+            yield resolve_service(
+                service_name, dns_client=dns_client_mock, cache=cache
+            )
+
+    @defer.inlineCallbacks
+    def test_name_error(self):
+        dns_client_mock = Mock()
+
+        dns_client_mock.lookupService.return_value = defer.fail(error.DNSNameError())
+
+        service_name = "test_service.examle.com"
+
+        cache = {}
+
+        servers = yield resolve_service(
+            service_name, dns_client=dns_client_mock, cache=cache
+        )
+
+        self.assertEquals(len(servers), 0)
+        self.assertEquals(len(cache), 0)
diff --git a/tests/test_state.py b/tests/test_state.py
index e4e995b756..a1ea7ef672 100644
--- a/tests/test_state.py
+++ b/tests/test_state.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2014 OpenMarket Ltd
+# Copyright 2014-2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/tests/test_test_utils.py b/tests/test_test_utils.py
index b42787dd25..3718f4fc3f 100644
--- a/tests/test_test_utils.py
+++ b/tests/test_test_utils.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2014 OpenMarket Ltd
+# Copyright 2014-2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/tests/test_types.py b/tests/test_types.py
index 495cd20f02..24d61dbe54 100644
--- a/tests/test_types.py
+++ b/tests/test_types.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2014 OpenMarket Ltd
+# Copyright 2014-2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -16,10 +16,10 @@
 from tests import unittest
 
 from synapse.api.errors import SynapseError
-from synapse.server import BaseHomeServer
+from synapse.server import HomeServer
 from synapse.types import UserID, RoomAlias
 
-mock_homeserver = BaseHomeServer(hostname="my.domain")
+mock_homeserver = HomeServer(hostname="my.domain")
 
 
 class UserIDTestCase(unittest.TestCase):
@@ -34,7 +34,6 @@ class UserIDTestCase(unittest.TestCase):
         with self.assertRaises(SynapseError):
             UserID.from_string("")
 
-
     def test_build(self):
         user = UserID("5678efgh", "my.domain")
 
diff --git a/tests/unittest.py b/tests/unittest.py
index fe26b7574f..6f02eb4cac 100644
--- a/tests/unittest.py
+++ b/tests/unittest.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2014 OpenMarket Ltd
+# Copyright 2014-2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/tests/util/__init__.py b/tests/util/__init__.py
index 9bff9ec169..d0e9399dda 100644
--- a/tests/util/__init__.py
+++ b/tests/util/__init__.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2014 OpenMarket Ltd
+# Copyright 2014-2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/tests/util/test_dict_cache.py b/tests/util/test_dict_cache.py
index 54ff26cd97..7bbe795622 100644
--- a/tests/util/test_dict_cache.py
+++ b/tests/util/test_dict_cache.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2015 OpenMarket Ltd
+# Copyright 2015, 2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/tests/util/test_log_context.py b/tests/util/test_log_context.py
index efa0f28bad..65a330a0e9 100644
--- a/tests/util/test_log_context.py
+++ b/tests/util/test_log_context.py
@@ -5,6 +5,7 @@ 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):
@@ -17,15 +18,6 @@ class LoggingContextTestCase(unittest.TestCase):
             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
diff --git a/tests/util/test_lrucache.py b/tests/util/test_lrucache.py
index fc5a904323..bab366fb7f 100644
--- a/tests/util/test_lrucache.py
+++ b/tests/util/test_lrucache.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2015 OpenMarket Ltd
+# Copyright 2015, 2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -17,6 +17,8 @@
 from .. import unittest
 
 from synapse.util.caches.lrucache import LruCache
+from synapse.util.caches.treecache import TreeCache
+
 
 class LruCacheTestCase(unittest.TestCase):
 
@@ -52,3 +54,28 @@ class LruCacheTestCase(unittest.TestCase):
         cache["key"] = 1
         self.assertEquals(cache.pop("key"), 1)
         self.assertEquals(cache.pop("key"), None)
+
+    def test_del_multi(self):
+        cache = LruCache(4, 2, cache_type=TreeCache)
+        cache[("animal", "cat")] = "mew"
+        cache[("animal", "dog")] = "woof"
+        cache[("vehicles", "car")] = "vroom"
+        cache[("vehicles", "train")] = "chuff"
+
+        self.assertEquals(len(cache), 4)
+
+        self.assertEquals(cache.get(("animal", "cat")), "mew")
+        self.assertEquals(cache.get(("vehicles", "car")), "vroom")
+        cache.del_multi(("animal",))
+        self.assertEquals(len(cache), 2)
+        self.assertEquals(cache.get(("animal", "cat")), None)
+        self.assertEquals(cache.get(("animal", "dog")), None)
+        self.assertEquals(cache.get(("vehicles", "car")), "vroom")
+        self.assertEquals(cache.get(("vehicles", "train")), "chuff")
+        # Man from del_multi say "Yes".
+
+    def test_clear(self):
+        cache = LruCache(1)
+        cache["key"] = 1
+        cache.clear()
+        self.assertEquals(len(cache), 0)
diff --git a/tests/util/test_snapshot_cache.py b/tests/util/test_snapshot_cache.py
index f58576c941..4ee0d49673 100644
--- a/tests/util/test_snapshot_cache.py
+++ b/tests/util/test_snapshot_cache.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2015 OpenMarket Ltd
+# Copyright 2015, 2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/tests/util/test_treecache.py b/tests/util/test_treecache.py
new file mode 100644
index 0000000000..1efbeb6b33
--- /dev/null
+++ b/tests/util/test_treecache.py
@@ -0,0 +1,78 @@
+# -*- coding: utf-8 -*-
+# Copyright 2015, 2016 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 .. import unittest
+
+from synapse.util.caches.treecache import TreeCache
+
+class TreeCacheTestCase(unittest.TestCase):
+    def test_get_set_onelevel(self):
+        cache = TreeCache()
+        cache[("a",)] = "A"
+        cache[("b",)] = "B"
+        self.assertEquals(cache.get(("a",)), "A")
+        self.assertEquals(cache.get(("b",)), "B")
+        self.assertEquals(len(cache), 2)
+
+    def test_pop_onelevel(self):
+        cache = TreeCache()
+        cache[("a",)] = "A"
+        cache[("b",)] = "B"
+        self.assertEquals(cache.pop(("a",)), "A")
+        self.assertEquals(cache.pop(("a",)), None)
+        self.assertEquals(cache.get(("b",)), "B")
+        self.assertEquals(len(cache), 1)
+
+    def test_get_set_twolevel(self):
+        cache = TreeCache()
+        cache[("a", "a")] = "AA"
+        cache[("a", "b")] = "AB"
+        cache[("b", "a")] = "BA"
+        self.assertEquals(cache.get(("a", "a")), "AA")
+        self.assertEquals(cache.get(("a", "b")), "AB")
+        self.assertEquals(cache.get(("b", "a")), "BA")
+        self.assertEquals(len(cache), 3)
+
+    def test_pop_twolevel(self):
+        cache = TreeCache()
+        cache[("a", "a")] = "AA"
+        cache[("a", "b")] = "AB"
+        cache[("b", "a")] = "BA"
+        self.assertEquals(cache.pop(("a", "a")), "AA")
+        self.assertEquals(cache.get(("a", "a")), None)
+        self.assertEquals(cache.get(("a", "b")), "AB")
+        self.assertEquals(cache.pop(("b", "a")), "BA")
+        self.assertEquals(cache.pop(("b", "a")), None)
+        self.assertEquals(len(cache), 1)
+
+    def test_pop_mixedlevel(self):
+        cache = TreeCache()
+        cache[("a", "a")] = "AA"
+        cache[("a", "b")] = "AB"
+        cache[("b", "a")] = "BA"
+        self.assertEquals(cache.get(("a", "a")), "AA")
+        cache.pop(("a",))
+        self.assertEquals(cache.get(("a", "a")), None)
+        self.assertEquals(cache.get(("a", "b")), None)
+        self.assertEquals(cache.get(("b", "a")), "BA")
+        self.assertEquals(len(cache), 1)
+
+    def test_clear(self):
+        cache = TreeCache()
+        cache[("a",)] = "A"
+        cache[("b",)] = "B"
+        cache.clear()
+        self.assertEquals(len(cache), 0)
diff --git a/tests/utils.py b/tests/utils.py
index aee69b1caa..3b1eb50d8d 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2014 OpenMarket Ltd
+# Copyright 2014-2016 OpenMarket Ltd
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -19,6 +19,8 @@ from synapse.api.constants import EventTypes
 from synapse.storage.prepare_database import prepare_database
 from synapse.storage.engines import create_engine
 from synapse.server import HomeServer
+from synapse.federation.transport import server
+from synapse.util.ratelimitutils import FederationRateLimiter
 
 from synapse.util.logcontext import LoggingContext
 
@@ -44,9 +46,10 @@ def setup_test_homeserver(name="test", datastore=None, config=None, **kargs):
         config = Mock()
         config.signing_key = [MockKey()]
         config.event_cache_size = 1
-        config.disable_registration = False
+        config.enable_registration = True
         config.macaroon_secret_key = "not even a little secret"
         config.server_name = "server.under.test"
+        config.trusted_third_party_id_servers = []
 
     if "clock" not in kargs:
         kargs["clock"] = MockClock()
@@ -58,8 +61,10 @@ def setup_test_homeserver(name="test", datastore=None, config=None, **kargs):
             name, db_pool=db_pool, config=config,
             version_string="Synapse/tests",
             database_engine=create_engine("sqlite3"),
+            get_db_conn=db_pool.get_db_conn,
             **kargs
         )
+        hs.setup()
     else:
         hs = HomeServer(
             name, db_pool=None, datastore=datastore, config=config,
@@ -80,6 +85,22 @@ def setup_test_homeserver(name="test", datastore=None, config=None, **kargs):
 
     hs.build_handlers = swap_out_hash_for_testing(hs.build_handlers)
 
+    fed = kargs.get("resource_for_federation", None)
+    if fed:
+        server.register_servlets(
+            hs,
+            resource=fed,
+            authenticator=server.Authenticator(hs),
+            ratelimiter=FederationRateLimiter(
+                hs.get_clock(),
+                window_size=hs.config.federation_rc_window_size,
+                sleep_limit=hs.config.federation_rc_sleep_limit,
+                sleep_msec=hs.config.federation_rc_sleep_delay,
+                reject_limit=hs.config.federation_rc_reject_limit,
+                concurrent_requests=hs.config.federation_rc_concurrent
+            ),
+        )
+
     defer.returnValue(hs)
 
 
@@ -262,6 +283,12 @@ class SQLiteMemoryDbPool(ConnectionPool, object):
             lambda conn: prepare_database(conn, engine)
         )
 
+    def get_db_conn(self):
+        conn = self.connect()
+        engine = create_engine("sqlite3")
+        prepare_database(conn, engine)
+        return conn
+
 
 class MemoryDataStore(object):