0
0
Fork 1
mirror of https://mau.dev/maunium/synapse.git synced 2024-06-17 01:59:26 +02:00

Run tests under PostgreSQL (#3423)

This commit is contained in:
Amber Brown 2018-08-13 16:47:46 +10:00 committed by GitHub
parent a001038b92
commit 99dd975dae
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
49 changed files with 227 additions and 59 deletions

View file

@ -8,6 +8,9 @@ before_script:
- git remote set-branches --add origin develop - git remote set-branches --add origin develop
- git fetch origin develop - git fetch origin develop
services:
- postgresql
matrix: matrix:
fast_finish: true fast_finish: true
include: include:
@ -20,6 +23,9 @@ matrix:
- python: 2.7 - python: 2.7
env: TOX_ENV=py27 env: TOX_ENV=py27
- python: 2.7
env: TOX_ENV=py27-postgres TRIAL_FLAGS="-j 4"
- python: 3.6 - python: 3.6
env: TOX_ENV=py36 env: TOX_ENV=py36
@ -29,6 +35,10 @@ matrix:
- python: 3.6 - python: 3.6
env: TOX_ENV=check-newsfragment env: TOX_ENV=check-newsfragment
allow_failures:
- python: 2.7
env: TOX_ENV=py27-postgres TRIAL_FLAGS="-j 4"
install: install:
- pip install tox - pip install tox

1
changelog.d/3423.misc Normal file
View file

@ -0,0 +1 @@
The test suite now can run under PostgreSQL.

View file

@ -95,6 +95,7 @@ class PresenceHandler(object):
Args: Args:
hs (synapse.server.HomeServer): hs (synapse.server.HomeServer):
""" """
self.hs = hs
self.is_mine = hs.is_mine self.is_mine = hs.is_mine
self.is_mine_id = hs.is_mine_id self.is_mine_id = hs.is_mine_id
self.clock = hs.get_clock() self.clock = hs.get_clock()
@ -230,6 +231,10 @@ class PresenceHandler(object):
earlier than they should when synapse is restarted. This affect of this earlier than they should when synapse is restarted. This affect of this
is some spurious presence changes that will self-correct. is some spurious presence changes that will self-correct.
""" """
# If the DB pool has already terminated, don't try updating
if not self.hs.get_db_pool().running:
return
logger.info( logger.info(
"Performing _on_shutdown. Persisting %d unpersisted changes", "Performing _on_shutdown. Persisting %d unpersisted changes",
len(self.user_to_current_state) len(self.user_to_current_state)

View file

@ -96,6 +96,11 @@ class ClientIpStore(background_updates.BackgroundUpdateStore):
self._batch_row_update[key] = (user_agent, device_id, now) self._batch_row_update[key] = (user_agent, device_id, now)
def _update_client_ips_batch(self): def _update_client_ips_batch(self):
# If the DB pool has already terminated, don't try updating
if not self.hs.get_db_pool().running:
return
def update(): def update():
to_update = self._batch_row_update to_update = self._batch_row_update
self._batch_row_update = {} self._batch_row_update = {}

View file

@ -15,4 +15,7 @@
from twisted.trial import util from twisted.trial import util
from tests import utils
util.DEFAULT_TIMEOUT_DURATION = 10 util.DEFAULT_TIMEOUT_DURATION = 10
utils.setupdb()

View file

@ -39,7 +39,7 @@ class AuthTestCase(unittest.TestCase):
self.state_handler = Mock() self.state_handler = Mock()
self.store = Mock() self.store = Mock()
self.hs = yield setup_test_homeserver(handlers=None) self.hs = yield setup_test_homeserver(self.addCleanup, handlers=None)
self.hs.get_datastore = Mock(return_value=self.store) self.hs.get_datastore = Mock(return_value=self.store)
self.hs.handlers = TestHandlers(self.hs) self.hs.handlers = TestHandlers(self.hs)
self.auth = Auth(self.hs) self.auth = Auth(self.hs)

View file

@ -46,7 +46,10 @@ class FilteringTestCase(unittest.TestCase):
self.mock_http_client.put_json = DeferredMockCallable() self.mock_http_client.put_json = DeferredMockCallable()
hs = yield setup_test_homeserver( hs = yield setup_test_homeserver(
handlers=None, http_client=self.mock_http_client, keyring=Mock() self.addCleanup,
handlers=None,
http_client=self.mock_http_client,
keyring=Mock(),
) )
self.filtering = hs.get_filtering() self.filtering = hs.get_filtering()

View file

@ -58,12 +58,10 @@ class KeyringTestCase(unittest.TestCase):
self.mock_perspective_server = MockPerspectiveServer() self.mock_perspective_server = MockPerspectiveServer()
self.http_client = Mock() self.http_client = Mock()
self.hs = yield utils.setup_test_homeserver( self.hs = yield utils.setup_test_homeserver(
handlers=None, http_client=self.http_client self.addCleanup, handlers=None, http_client=self.http_client
) )
keys = self.mock_perspective_server.get_verify_keys() keys = self.mock_perspective_server.get_verify_keys()
self.hs.config.perspectives = { self.hs.config.perspectives = {self.mock_perspective_server.server_name: keys}
self.mock_perspective_server.server_name: keys
}
def check_context(self, _, expected): def check_context(self, _, expected):
self.assertEquals( self.assertEquals(

View file

@ -35,7 +35,7 @@ class AuthHandlers(object):
class AuthTestCase(unittest.TestCase): class AuthTestCase(unittest.TestCase):
@defer.inlineCallbacks @defer.inlineCallbacks
def setUp(self): def setUp(self):
self.hs = yield setup_test_homeserver(handlers=None) self.hs = yield setup_test_homeserver(self.addCleanup, handlers=None)
self.hs.handlers = AuthHandlers(self.hs) self.hs.handlers = AuthHandlers(self.hs)
self.auth_handler = self.hs.handlers.auth_handler self.auth_handler = self.hs.handlers.auth_handler
self.macaroon_generator = self.hs.get_macaroon_generator() self.macaroon_generator = self.hs.get_macaroon_generator()

View file

@ -34,7 +34,7 @@ class DeviceTestCase(unittest.TestCase):
@defer.inlineCallbacks @defer.inlineCallbacks
def setUp(self): def setUp(self):
hs = yield utils.setup_test_homeserver() hs = yield utils.setup_test_homeserver(self.addCleanup)
self.handler = hs.get_device_handler() self.handler = hs.get_device_handler()
self.store = hs.get_datastore() self.store = hs.get_datastore()
self.clock = hs.get_clock() self.clock = hs.get_clock()

View file

@ -46,6 +46,7 @@ class DirectoryTestCase(unittest.TestCase):
self.mock_registry.register_query_handler = register_query_handler self.mock_registry.register_query_handler = register_query_handler
hs = yield setup_test_homeserver( hs = yield setup_test_homeserver(
self.addCleanup,
http_client=None, http_client=None,
resource_for_federation=Mock(), resource_for_federation=Mock(),
federation_client=self.mock_federation, federation_client=self.mock_federation,

View file

@ -34,7 +34,7 @@ class E2eKeysHandlerTestCase(unittest.TestCase):
@defer.inlineCallbacks @defer.inlineCallbacks
def setUp(self): def setUp(self):
self.hs = yield utils.setup_test_homeserver( self.hs = yield utils.setup_test_homeserver(
handlers=None, federation_client=mock.Mock() self.addCleanup, handlers=None, federation_client=mock.Mock()
) )
self.handler = synapse.handlers.e2e_keys.E2eKeysHandler(self.hs) self.handler = synapse.handlers.e2e_keys.E2eKeysHandler(self.hs)

View file

@ -48,6 +48,7 @@ class ProfileTestCase(unittest.TestCase):
self.mock_registry.register_query_handler = register_query_handler self.mock_registry.register_query_handler = register_query_handler
hs = yield setup_test_homeserver( hs = yield setup_test_homeserver(
self.addCleanup,
http_client=None, http_client=None,
handlers=None, handlers=None,
resource_for_federation=Mock(), resource_for_federation=Mock(),

View file

@ -40,6 +40,7 @@ class RegistrationTestCase(unittest.TestCase):
self.mock_distributor.declare("registered_user") self.mock_distributor.declare("registered_user")
self.mock_captcha_client = Mock() self.mock_captcha_client = Mock()
self.hs = yield setup_test_homeserver( self.hs = yield setup_test_homeserver(
self.addCleanup,
handlers=None, handlers=None,
http_client=None, http_client=None,
expire_access_token=True, expire_access_token=True,

View file

@ -67,6 +67,7 @@ class TypingNotificationsTestCase(unittest.TestCase):
self.state_handler = Mock() self.state_handler = Mock()
hs = yield setup_test_homeserver( hs = yield setup_test_homeserver(
self.addCleanup,
"test", "test",
auth=self.auth, auth=self.auth,
clock=self.clock, clock=self.clock,

View file

@ -54,6 +54,7 @@ class BaseSlavedStoreTestCase(unittest.TestCase):
@defer.inlineCallbacks @defer.inlineCallbacks
def setUp(self): def setUp(self):
self.hs = yield setup_test_homeserver( self.hs = yield setup_test_homeserver(
self.addCleanup,
"blue", "blue",
http_client=None, http_client=None,
federation_client=Mock(), federation_client=Mock(),

View file

@ -51,7 +51,7 @@ class UserRegisterTestCase(unittest.TestCase):
self.secrets = Mock() self.secrets = Mock()
self.hs = setup_test_homeserver( self.hs = setup_test_homeserver(
http_client=None, clock=self.hs_clock, reactor=self.clock self.addCleanup, http_client=None, clock=self.hs_clock, reactor=self.clock
) )
self.hs.config.registration_shared_secret = u"shared" self.hs.config.registration_shared_secret = u"shared"

View file

@ -41,6 +41,7 @@ class EventStreamPermissionsTestCase(RestTestCase):
self.mock_resource = MockHttpResource(prefix=PATH_PREFIX) self.mock_resource = MockHttpResource(prefix=PATH_PREFIX)
hs = yield setup_test_homeserver( hs = yield setup_test_homeserver(
self.addCleanup,
http_client=None, http_client=None,
federation_client=Mock(), federation_client=Mock(),
ratelimiter=NonCallableMock(spec_set=["send_message"]), ratelimiter=NonCallableMock(spec_set=["send_message"]),

View file

@ -46,6 +46,7 @@ class ProfileTestCase(unittest.TestCase):
) )
hs = yield setup_test_homeserver( hs = yield setup_test_homeserver(
self.addCleanup,
"test", "test",
http_client=None, http_client=None,
resource_for_client=self.mock_resource, resource_for_client=self.mock_resource,

View file

@ -49,7 +49,7 @@ class CreateUserServletTestCase(unittest.TestCase):
self.hs_clock = Clock(self.clock) self.hs_clock = Clock(self.clock)
self.hs = self.hs = setup_test_homeserver( self.hs = self.hs = setup_test_homeserver(
http_client=None, clock=self.hs_clock, reactor=self.clock self.addCleanup, http_client=None, clock=self.hs_clock, reactor=self.clock
) )
self.hs.get_datastore = Mock(return_value=self.datastore) self.hs.get_datastore = Mock(return_value=self.datastore)
self.hs.get_handlers = Mock(return_value=handlers) self.hs.get_handlers = Mock(return_value=handlers)

View file

@ -50,6 +50,7 @@ class RoomBase(unittest.TestCase):
self.hs_clock = Clock(self.clock) self.hs_clock = Clock(self.clock)
self.hs = setup_test_homeserver( self.hs = setup_test_homeserver(
self.addCleanup,
"red", "red",
http_client=None, http_client=None,
clock=self.hs_clock, clock=self.hs_clock,

View file

@ -44,6 +44,7 @@ class RoomTypingTestCase(RestTestCase):
self.auth_user_id = self.user_id self.auth_user_id = self.user_id
hs = yield setup_test_homeserver( hs = yield setup_test_homeserver(
self.addCleanup,
"red", "red",
clock=self.clock, clock=self.clock,
http_client=None, http_client=None,

View file

@ -43,7 +43,7 @@ class FilterTestCase(unittest.TestCase):
self.hs_clock = Clock(self.clock) self.hs_clock = Clock(self.clock)
self.hs = setup_test_homeserver( self.hs = setup_test_homeserver(
http_client=None, clock=self.hs_clock, reactor=self.clock self.addCleanup, http_client=None, clock=self.hs_clock, reactor=self.clock
) )
self.auth = self.hs.get_auth() self.auth = self.hs.get_auth()

View file

@ -47,7 +47,7 @@ class RegisterRestServletTestCase(unittest.TestCase):
login_handler=self.login_handler, login_handler=self.login_handler,
) )
self.hs = setup_test_homeserver( self.hs = setup_test_homeserver(
http_client=None, clock=self.hs_clock, reactor=self.clock self.addCleanup, http_client=None, clock=self.hs_clock, reactor=self.clock
) )
self.hs.get_auth = Mock(return_value=self.auth) self.hs.get_auth = Mock(return_value=self.auth)
self.hs.get_handlers = Mock(return_value=self.handlers) self.hs.get_handlers = Mock(return_value=self.handlers)

View file

@ -40,7 +40,7 @@ class FilterTestCase(unittest.TestCase):
self.hs_clock = Clock(self.clock) self.hs_clock = Clock(self.clock)
self.hs = setup_test_homeserver( self.hs = setup_test_homeserver(
http_client=None, clock=self.hs_clock, reactor=self.clock self.addCleanup, http_client=None, clock=self.hs_clock, reactor=self.clock
) )
self.auth = self.hs.get_auth() self.auth = self.hs.get_auth()

View file

@ -147,12 +147,15 @@ class ThreadedMemoryReactorClock(MemoryReactorClock):
return d return d
def setup_test_homeserver(*args, **kwargs): def setup_test_homeserver(cleanup_func, *args, **kwargs):
""" """
Set up a synchronous test server, driven by the reactor used by Set up a synchronous test server, driven by the reactor used by
the homeserver. the homeserver.
""" """
d = _sth(*args, **kwargs).result d = _sth(cleanup_func, *args, **kwargs).result
if isinstance(d, Failure):
d.raiseException()
# Make the thread pool synchronous. # Make the thread pool synchronous.
clock = d.get_clock() clock = d.get_clock()
@ -189,6 +192,9 @@ def setup_test_homeserver(*args, **kwargs):
def start(self): def start(self):
pass pass
def stop(self):
pass
def callInThreadWithCallback(self, onResult, function, *args, **kwargs): def callInThreadWithCallback(self, onResult, function, *args, **kwargs):
def _(res): def _(res):
if isinstance(res, Failure): if isinstance(res, Failure):

View file

@ -43,7 +43,10 @@ class ApplicationServiceStoreTestCase(unittest.TestCase):
password_providers=[], password_providers=[],
) )
hs = yield setup_test_homeserver( hs = yield setup_test_homeserver(
config=config, federation_sender=Mock(), federation_client=Mock() self.addCleanup,
config=config,
federation_sender=Mock(),
federation_client=Mock(),
) )
self.as_token = "token1" self.as_token = "token1"
@ -108,7 +111,10 @@ class ApplicationServiceTransactionStoreTestCase(unittest.TestCase):
password_providers=[], password_providers=[],
) )
hs = yield setup_test_homeserver( hs = yield setup_test_homeserver(
config=config, federation_sender=Mock(), federation_client=Mock() self.addCleanup,
config=config,
federation_sender=Mock(),
federation_client=Mock(),
) )
self.db_pool = hs.get_db_pool() self.db_pool = hs.get_db_pool()
@ -392,6 +398,7 @@ class ApplicationServiceStoreConfigTestCase(unittest.TestCase):
app_service_config_files=[f1, f2], event_cache_size=1, password_providers=[] app_service_config_files=[f1, f2], event_cache_size=1, password_providers=[]
) )
hs = yield setup_test_homeserver( hs = yield setup_test_homeserver(
self.addCleanup,
config=config, config=config,
datastore=Mock(), datastore=Mock(),
federation_sender=Mock(), federation_sender=Mock(),
@ -409,6 +416,7 @@ class ApplicationServiceStoreConfigTestCase(unittest.TestCase):
app_service_config_files=[f1, f2], event_cache_size=1, password_providers=[] app_service_config_files=[f1, f2], event_cache_size=1, password_providers=[]
) )
hs = yield setup_test_homeserver( hs = yield setup_test_homeserver(
self.addCleanup,
config=config, config=config,
datastore=Mock(), datastore=Mock(),
federation_sender=Mock(), federation_sender=Mock(),
@ -432,6 +440,7 @@ class ApplicationServiceStoreConfigTestCase(unittest.TestCase):
app_service_config_files=[f1, f2], event_cache_size=1, password_providers=[] app_service_config_files=[f1, f2], event_cache_size=1, password_providers=[]
) )
hs = yield setup_test_homeserver( hs = yield setup_test_homeserver(
self.addCleanup,
config=config, config=config,
datastore=Mock(), datastore=Mock(),
federation_sender=Mock(), federation_sender=Mock(),

View file

@ -9,7 +9,9 @@ from tests.utils import setup_test_homeserver
class BackgroundUpdateTestCase(unittest.TestCase): class BackgroundUpdateTestCase(unittest.TestCase):
@defer.inlineCallbacks @defer.inlineCallbacks
def setUp(self): def setUp(self):
hs = yield setup_test_homeserver() # type: synapse.server.HomeServer hs = yield setup_test_homeserver(
self.addCleanup
) # type: synapse.server.HomeServer
self.store = hs.get_datastore() self.store = hs.get_datastore()
self.clock = hs.get_clock() self.clock = hs.get_clock()

View file

@ -28,7 +28,7 @@ class ClientIpStoreTestCase(tests.unittest.TestCase):
@defer.inlineCallbacks @defer.inlineCallbacks
def setUp(self): def setUp(self):
self.hs = yield tests.utils.setup_test_homeserver() self.hs = yield tests.utils.setup_test_homeserver(self.addCleanup)
self.store = self.hs.get_datastore() self.store = self.hs.get_datastore()
self.clock = self.hs.get_clock() self.clock = self.hs.get_clock()

View file

@ -28,7 +28,7 @@ class DeviceStoreTestCase(tests.unittest.TestCase):
@defer.inlineCallbacks @defer.inlineCallbacks
def setUp(self): def setUp(self):
hs = yield tests.utils.setup_test_homeserver() hs = yield tests.utils.setup_test_homeserver(self.addCleanup)
self.store = hs.get_datastore() self.store = hs.get_datastore()

View file

@ -26,7 +26,7 @@ from tests.utils import setup_test_homeserver
class DirectoryStoreTestCase(unittest.TestCase): class DirectoryStoreTestCase(unittest.TestCase):
@defer.inlineCallbacks @defer.inlineCallbacks
def setUp(self): def setUp(self):
hs = yield setup_test_homeserver() hs = yield setup_test_homeserver(self.addCleanup)
self.store = DirectoryStore(None, hs) self.store = DirectoryStore(None, hs)

View file

@ -26,8 +26,7 @@ class EndToEndKeyStoreTestCase(tests.unittest.TestCase):
@defer.inlineCallbacks @defer.inlineCallbacks
def setUp(self): def setUp(self):
hs = yield tests.utils.setup_test_homeserver() hs = yield tests.utils.setup_test_homeserver(self.addCleanup)
self.store = hs.get_datastore() self.store = hs.get_datastore()
@defer.inlineCallbacks @defer.inlineCallbacks

View file

@ -22,7 +22,7 @@ import tests.utils
class EventFederationWorkerStoreTestCase(tests.unittest.TestCase): class EventFederationWorkerStoreTestCase(tests.unittest.TestCase):
@defer.inlineCallbacks @defer.inlineCallbacks
def setUp(self): def setUp(self):
hs = yield tests.utils.setup_test_homeserver() hs = yield tests.utils.setup_test_homeserver(self.addCleanup)
self.store = hs.get_datastore() self.store = hs.get_datastore()
@defer.inlineCallbacks @defer.inlineCallbacks

View file

@ -33,7 +33,7 @@ HIGHLIGHT = [
class EventPushActionsStoreTestCase(tests.unittest.TestCase): class EventPushActionsStoreTestCase(tests.unittest.TestCase):
@defer.inlineCallbacks @defer.inlineCallbacks
def setUp(self): def setUp(self):
hs = yield tests.utils.setup_test_homeserver() hs = yield tests.utils.setup_test_homeserver(self.addCleanup)
self.store = hs.get_datastore() self.store = hs.get_datastore()
@defer.inlineCallbacks @defer.inlineCallbacks

View file

@ -28,7 +28,7 @@ class KeyStoreTestCase(tests.unittest.TestCase):
@defer.inlineCallbacks @defer.inlineCallbacks
def setUp(self): def setUp(self):
hs = yield tests.utils.setup_test_homeserver() hs = yield tests.utils.setup_test_homeserver(self.addCleanup)
self.store = hs.get_datastore() self.store = hs.get_datastore()
@defer.inlineCallbacks @defer.inlineCallbacks

View file

@ -28,7 +28,7 @@ class MonthlyActiveUsersTestCase(tests.unittest.TestCase):
@defer.inlineCallbacks @defer.inlineCallbacks
def setUp(self): def setUp(self):
self.hs = yield setup_test_homeserver() self.hs = yield setup_test_homeserver(self.addCleanup)
self.store = self.hs.get_datastore() self.store = self.hs.get_datastore()
@defer.inlineCallbacks @defer.inlineCallbacks

View file

@ -26,7 +26,7 @@ from tests.utils import MockClock, setup_test_homeserver
class PresenceStoreTestCase(unittest.TestCase): class PresenceStoreTestCase(unittest.TestCase):
@defer.inlineCallbacks @defer.inlineCallbacks
def setUp(self): def setUp(self):
hs = yield setup_test_homeserver(clock=MockClock()) hs = yield setup_test_homeserver(self.addCleanup, clock=MockClock())
self.store = PresenceStore(None, hs) self.store = PresenceStore(None, hs)

View file

@ -26,7 +26,7 @@ from tests.utils import setup_test_homeserver
class ProfileStoreTestCase(unittest.TestCase): class ProfileStoreTestCase(unittest.TestCase):
@defer.inlineCallbacks @defer.inlineCallbacks
def setUp(self): def setUp(self):
hs = yield setup_test_homeserver() hs = yield setup_test_homeserver(self.addCleanup)
self.store = ProfileStore(None, hs) self.store = ProfileStore(None, hs)

View file

@ -29,7 +29,7 @@ class RedactionTestCase(unittest.TestCase):
@defer.inlineCallbacks @defer.inlineCallbacks
def setUp(self): def setUp(self):
hs = yield setup_test_homeserver( hs = yield setup_test_homeserver(
resource_for_federation=Mock(), http_client=None self.addCleanup, resource_for_federation=Mock(), http_client=None
) )
self.store = hs.get_datastore() self.store = hs.get_datastore()

View file

@ -23,7 +23,7 @@ from tests.utils import setup_test_homeserver
class RegistrationStoreTestCase(unittest.TestCase): class RegistrationStoreTestCase(unittest.TestCase):
@defer.inlineCallbacks @defer.inlineCallbacks
def setUp(self): def setUp(self):
hs = yield setup_test_homeserver() hs = yield setup_test_homeserver(self.addCleanup)
self.db_pool = hs.get_db_pool() self.db_pool = hs.get_db_pool()
self.store = hs.get_datastore() self.store = hs.get_datastore()

View file

@ -26,7 +26,7 @@ from tests.utils import setup_test_homeserver
class RoomStoreTestCase(unittest.TestCase): class RoomStoreTestCase(unittest.TestCase):
@defer.inlineCallbacks @defer.inlineCallbacks
def setUp(self): def setUp(self):
hs = yield setup_test_homeserver() hs = yield setup_test_homeserver(self.addCleanup)
# We can't test RoomStore on its own without the DirectoryStore, for # We can't test RoomStore on its own without the DirectoryStore, for
# management of the 'room_aliases' table # management of the 'room_aliases' table
@ -57,7 +57,7 @@ class RoomStoreTestCase(unittest.TestCase):
class RoomEventsStoreTestCase(unittest.TestCase): class RoomEventsStoreTestCase(unittest.TestCase):
@defer.inlineCallbacks @defer.inlineCallbacks
def setUp(self): def setUp(self):
hs = setup_test_homeserver() hs = setup_test_homeserver(self.addCleanup)
# Room events need the full datastore, for persist_event() and # Room events need the full datastore, for persist_event() and
# get_room_state() # get_room_state()

View file

@ -29,7 +29,7 @@ class RoomMemberStoreTestCase(unittest.TestCase):
@defer.inlineCallbacks @defer.inlineCallbacks
def setUp(self): def setUp(self):
hs = yield setup_test_homeserver( hs = yield setup_test_homeserver(
resource_for_federation=Mock(), http_client=None self.addCleanup, resource_for_federation=Mock(), http_client=None
) )
# We can't test the RoomMemberStore on its own without the other event # We can't test the RoomMemberStore on its own without the other event
# storage logic # storage logic

View file

@ -33,7 +33,7 @@ class StateStoreTestCase(tests.unittest.TestCase):
@defer.inlineCallbacks @defer.inlineCallbacks
def setUp(self): def setUp(self):
hs = yield tests.utils.setup_test_homeserver() hs = yield tests.utils.setup_test_homeserver(self.addCleanup)
self.store = hs.get_datastore() self.store = hs.get_datastore()
self.event_builder_factory = hs.get_event_builder_factory() self.event_builder_factory = hs.get_event_builder_factory()

View file

@ -29,7 +29,7 @@ BOBBY = "@bobby:a"
class UserDirectoryStoreTestCase(unittest.TestCase): class UserDirectoryStoreTestCase(unittest.TestCase):
@defer.inlineCallbacks @defer.inlineCallbacks
def setUp(self): def setUp(self):
self.hs = yield setup_test_homeserver() self.hs = yield setup_test_homeserver(self.addCleanup)
self.store = UserDirectoryStore(None, self.hs) self.store = UserDirectoryStore(None, self.hs)
# alice and bob are both in !room_id. bobby is not but shares # alice and bob are both in !room_id. bobby is not but shares

View file

@ -18,7 +18,10 @@ class MessageAcceptTests(unittest.TestCase):
self.reactor = ThreadedMemoryReactorClock() self.reactor = ThreadedMemoryReactorClock()
self.hs_clock = Clock(self.reactor) self.hs_clock = Clock(self.reactor)
self.homeserver = setup_test_homeserver( self.homeserver = setup_test_homeserver(
http_client=self.http_client, clock=self.hs_clock, reactor=self.reactor self.addCleanup,
http_client=self.http_client,
clock=self.hs_clock,
reactor=self.reactor,
) )
user_id = UserID("us", "test") user_id = UserID("us", "test")

View file

@ -16,7 +16,7 @@ class JsonResourceTests(unittest.TestCase):
self.reactor = MemoryReactorClock() self.reactor = MemoryReactorClock()
self.hs_clock = Clock(self.reactor) self.hs_clock = Clock(self.reactor)
self.homeserver = setup_test_homeserver( self.homeserver = setup_test_homeserver(
http_client=None, clock=self.hs_clock, reactor=self.reactor self.addCleanup, http_client=None, clock=self.hs_clock, reactor=self.reactor
) )
def test_handler_for_request(self): def test_handler_for_request(self):

View file

@ -31,7 +31,7 @@ TEST_ROOM_ID = "!TEST:ROOM"
class FilterEventsForServerTestCase(tests.unittest.TestCase): class FilterEventsForServerTestCase(tests.unittest.TestCase):
@defer.inlineCallbacks @defer.inlineCallbacks
def setUp(self): def setUp(self):
self.hs = yield setup_test_homeserver() self.hs = yield setup_test_homeserver(self.addCleanup)
self.event_creation_handler = self.hs.get_event_creation_handler() self.event_creation_handler = self.hs.get_event_creation_handler()
self.event_builder_factory = self.hs.get_event_builder_factory() self.event_builder_factory = self.hs.get_event_builder_factory()
self.store = self.hs.get_datastore() self.store = self.hs.get_datastore()

View file

@ -13,7 +13,10 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import atexit
import hashlib import hashlib
import os
import uuid
from inspect import getcallargs from inspect import getcallargs
from mock import Mock, patch from mock import Mock, patch
@ -27,23 +30,80 @@ from synapse.http.server import HttpServer
from synapse.server import HomeServer from synapse.server import HomeServer
from synapse.storage import PostgresEngine from synapse.storage import PostgresEngine
from synapse.storage.engines import create_engine from synapse.storage.engines import create_engine
from synapse.storage.prepare_database import prepare_database from synapse.storage.prepare_database import (
_get_or_create_schema_state,
_setup_new_database,
prepare_database,
)
from synapse.util.logcontext import LoggingContext from synapse.util.logcontext import LoggingContext
from synapse.util.ratelimitutils import FederationRateLimiter from synapse.util.ratelimitutils import FederationRateLimiter
# set this to True to run the tests against postgres instead of sqlite. # set this to True to run the tests against postgres instead of sqlite.
# It requires you to have a local postgres database called synapse_test, within USE_POSTGRES_FOR_TESTS = os.environ.get("SYNAPSE_POSTGRES", False)
# which ALL TABLES WILL BE DROPPED POSTGRES_USER = os.environ.get("SYNAPSE_POSTGRES_USER", "postgres")
USE_POSTGRES_FOR_TESTS = False POSTGRES_BASE_DB = "_synapse_unit_tests_base_%s" % (os.getpid(),)
def setupdb():
# If we're using PostgreSQL, set up the db once
if USE_POSTGRES_FOR_TESTS:
pgconfig = {
"name": "psycopg2",
"args": {
"database": POSTGRES_BASE_DB,
"user": POSTGRES_USER,
"cp_min": 1,
"cp_max": 5,
},
}
config = Mock()
config.password_providers = []
config.database_config = pgconfig
db_engine = create_engine(pgconfig)
db_conn = db_engine.module.connect(user=POSTGRES_USER)
db_conn.autocommit = True
cur = db_conn.cursor()
cur.execute("DROP DATABASE IF EXISTS %s;" % (POSTGRES_BASE_DB,))
cur.execute("CREATE DATABASE %s;" % (POSTGRES_BASE_DB,))
cur.close()
db_conn.close()
# Set up in the db
db_conn = db_engine.module.connect(
database=POSTGRES_BASE_DB, user=POSTGRES_USER
)
cur = db_conn.cursor()
_get_or_create_schema_state(cur, db_engine)
_setup_new_database(cur, db_engine)
db_conn.commit()
cur.close()
db_conn.close()
def _cleanup():
db_conn = db_engine.module.connect(user=POSTGRES_USER)
db_conn.autocommit = True
cur = db_conn.cursor()
cur.execute("DROP DATABASE IF EXISTS %s;" % (POSTGRES_BASE_DB,))
cur.close()
db_conn.close()
atexit.register(_cleanup)
@defer.inlineCallbacks @defer.inlineCallbacks
def setup_test_homeserver( def setup_test_homeserver(
name="test", datastore=None, config=None, reactor=None, **kargs cleanup_func, name="test", datastore=None, config=None, reactor=None, **kargs
): ):
"""Setup a homeserver suitable for running tests against. Keyword arguments """
are passed to the Homeserver constructor. If no datastore is supplied a Setup a homeserver suitable for running tests against. Keyword arguments
datastore backed by an in-memory sqlite db will be given to the HS. are passed to the Homeserver constructor.
If no datastore is supplied, one is created and given to the homeserver.
Args:
cleanup_func : The function used to register a cleanup routine for
after the test.
""" """
if reactor is None: if reactor is None:
from twisted.internet import reactor from twisted.internet import reactor
@ -95,9 +155,11 @@ def setup_test_homeserver(
kargs["clock"] = MockClock() kargs["clock"] = MockClock()
if USE_POSTGRES_FOR_TESTS: if USE_POSTGRES_FOR_TESTS:
test_db = "synapse_test_%s" % uuid.uuid4().hex
config.database_config = { config.database_config = {
"name": "psycopg2", "name": "psycopg2",
"args": {"database": "synapse_test", "cp_min": 1, "cp_max": 5}, "args": {"database": test_db, "cp_min": 1, "cp_max": 5},
} }
else: else:
config.database_config = { config.database_config = {
@ -107,6 +169,21 @@ def setup_test_homeserver(
db_engine = create_engine(config.database_config) db_engine = create_engine(config.database_config)
# Create the database before we actually try and connect to it, based off
# the template database we generate in setupdb()
if datastore is None and isinstance(db_engine, PostgresEngine):
db_conn = db_engine.module.connect(
database=POSTGRES_BASE_DB, user=POSTGRES_USER
)
db_conn.autocommit = True
cur = db_conn.cursor()
cur.execute("DROP DATABASE IF EXISTS %s;" % (test_db,))
cur.execute(
"CREATE DATABASE %s WITH TEMPLATE %s;" % (test_db, POSTGRES_BASE_DB)
)
cur.close()
db_conn.close()
# we need to configure the connection pool to run the on_new_connection # we need to configure the connection pool to run the on_new_connection
# function, so that we can test code that uses custom sqlite functions # function, so that we can test code that uses custom sqlite functions
# (like rank). # (like rank).
@ -125,15 +202,35 @@ def setup_test_homeserver(
reactor=reactor, reactor=reactor,
**kargs **kargs
) )
db_conn = hs.get_db_conn()
# make sure that the database is empty # Prepare the DB on SQLite -- PostgreSQL is a copy of an already up to
if isinstance(db_engine, PostgresEngine): # date db
cur = db_conn.cursor() if not isinstance(db_engine, PostgresEngine):
cur.execute("SELECT tablename FROM pg_tables where schemaname='public'") db_conn = hs.get_db_conn()
rows = cur.fetchall() yield prepare_database(db_conn, db_engine, config)
for r in rows: db_conn.commit()
cur.execute("DROP TABLE %s CASCADE" % r[0]) db_conn.close()
yield prepare_database(db_conn, db_engine, config)
else:
# We need to do cleanup on PostgreSQL
def cleanup():
# Close all the db pools
hs.get_db_pool().close()
# Drop the test database
db_conn = db_engine.module.connect(
database=POSTGRES_BASE_DB, user=POSTGRES_USER
)
db_conn.autocommit = True
cur = db_conn.cursor()
cur.execute("DROP DATABASE IF EXISTS %s;" % (test_db,))
db_conn.commit()
cur.close()
db_conn.close()
# Register the cleanup hook
cleanup_func(cleanup)
hs.setup() hs.setup()
else: else:
hs = HomeServer( hs = HomeServer(

20
tox.ini
View file

@ -1,7 +1,7 @@
[tox] [tox]
envlist = packaging, py27, py36, pep8, check_isort envlist = packaging, py27, py36, pep8, check_isort
[testenv] [base]
deps = deps =
coverage coverage
Twisted>=15.1 Twisted>=15.1
@ -15,6 +15,15 @@ deps =
setenv = setenv =
PYTHONDONTWRITEBYTECODE = no_byte_code PYTHONDONTWRITEBYTECODE = no_byte_code
[testenv]
deps =
{[base]deps}
setenv =
{[base]setenv}
passenv = *
commands = commands =
/usr/bin/find "{toxinidir}" -name '*.pyc' -delete /usr/bin/find "{toxinidir}" -name '*.pyc' -delete
coverage run {env:COVERAGE_OPTS:} --source="{toxinidir}/synapse" \ coverage run {env:COVERAGE_OPTS:} --source="{toxinidir}/synapse" \
@ -46,6 +55,15 @@ commands =
# ) # )
usedevelop=true usedevelop=true
[testenv:py27-postgres]
usedevelop=true
deps =
{[base]deps}
psycopg2
setenv =
{[base]setenv}
SYNAPSE_POSTGRES = 1
[testenv:py36] [testenv:py36]
usedevelop=true usedevelop=true
commands = commands =