|
11 | 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12 | 12 | # See the License for the specific language governing permissions and
|
13 | 13 | # limitations under the License.
|
14 |
| -import hashlib |
| 14 | + |
15 | 15 | import json
|
16 | 16 | import logging
|
17 |
| -import time |
18 |
| -import uuid |
19 |
| -import warnings |
20 | 17 | from collections import deque
|
21 | 18 | from io import SEEK_END, BytesIO
|
22 | 19 | from typing import (
|
|
30 | 27 | Type,
|
31 | 28 | Union,
|
32 | 29 | )
|
33 |
| -from unittest.mock import Mock |
34 | 30 |
|
35 | 31 | import attr
|
36 | 32 | from typing_extensions import Deque
|
|
57 | 53 | from twisted.web.resource import IResource
|
58 | 54 | from twisted.web.server import Request, Site
|
59 | 55 |
|
60 |
| -from synapse.config.database import DatabaseConnectionConfig |
61 | 56 | from synapse.http.site import SynapseRequest
|
62 |
| -from synapse.server import HomeServer |
63 |
| -from synapse.storage import DataStore |
64 |
| -from synapse.storage.engines import PostgresEngine, create_engine |
65 | 57 | from synapse.types import JsonDict
|
66 | 58 | from synapse.util import Clock
|
67 | 59 |
|
68 |
| -from tests.utils import ( |
69 |
| - LEAVE_DB, |
70 |
| - POSTGRES_BASE_DB, |
71 |
| - POSTGRES_HOST, |
72 |
| - POSTGRES_PASSWORD, |
73 |
| - POSTGRES_USER, |
74 |
| - USE_POSTGRES_FOR_TESTS, |
75 |
| - MockClock, |
76 |
| - default_config, |
77 |
| -) |
| 60 | +from tests.utils import setup_test_homeserver as _sth |
78 | 61 |
|
79 | 62 | logger = logging.getLogger(__name__)
|
80 | 63 |
|
@@ -467,11 +450,14 @@ def _(res):
|
467 | 450 | return d
|
468 | 451 |
|
469 | 452 |
|
470 |
| -def make_test_homeserver_synchronous(server: HomeServer) -> None: |
| 453 | +def setup_test_homeserver(cleanup_func, *args, **kwargs): |
471 | 454 | """
|
472 |
| - Make the given test homeserver's database interactions synchronous. |
| 455 | + Set up a synchronous test server, driven by the reactor used by |
| 456 | + the homeserver. |
473 | 457 | """
|
| 458 | + server = _sth(cleanup_func, *args, **kwargs) |
474 | 459 |
|
| 460 | + # Make the thread pool synchronous. |
475 | 461 | clock = server.get_clock()
|
476 | 462 |
|
477 | 463 | for database in server.get_datastores().databases:
|
@@ -499,14 +485,15 @@ def runInteraction(interaction, *args, **kwargs):
|
499 | 485 |
|
500 | 486 | pool.runWithConnection = runWithConnection
|
501 | 487 | pool.runInteraction = runInteraction
|
502 |
| - # Replace the thread pool with a threadless 'thread' pool |
503 | 488 | pool.threadpool = ThreadPool(clock._reactor)
|
504 | 489 | pool.running = True
|
505 | 490 |
|
506 | 491 | # We've just changed the Databases to run DB transactions on the same
|
507 | 492 | # thread, so we need to disable the dedicated thread behaviour.
|
508 | 493 | server.get_datastores().main.USE_DEDICATED_DB_THREADS_FOR_EVENT_FETCHING = False
|
509 | 494 |
|
| 495 | + return server |
| 496 | + |
510 | 497 |
|
511 | 498 | def get_clock() -> Tuple[ThreadedMemoryReactorClock, Clock]:
|
512 | 499 | clock = ThreadedMemoryReactorClock()
|
@@ -686,171 +673,3 @@ def connect_client(
|
686 | 673 | client.makeConnection(FakeTransport(server, reactor))
|
687 | 674 |
|
688 | 675 | return client, server
|
689 |
| - |
690 |
| - |
691 |
| -class TestHomeServer(HomeServer): |
692 |
| - DATASTORE_CLASS = DataStore |
693 |
| - |
694 |
| - |
695 |
| -def setup_test_homeserver( |
696 |
| - cleanup_func, |
697 |
| - name="test", |
698 |
| - config=None, |
699 |
| - reactor=None, |
700 |
| - homeserver_to_use: Type[HomeServer] = TestHomeServer, |
701 |
| - **kwargs, |
702 |
| -): |
703 |
| - """ |
704 |
| - Setup a homeserver suitable for running tests against. Keyword arguments |
705 |
| - are passed to the Homeserver constructor. |
706 |
| -
|
707 |
| - If no datastore is supplied, one is created and given to the homeserver. |
708 |
| -
|
709 |
| - Args: |
710 |
| - cleanup_func : The function used to register a cleanup routine for |
711 |
| - after the test. |
712 |
| -
|
713 |
| - Calling this method directly is deprecated: you should instead derive from |
714 |
| - HomeserverTestCase. |
715 |
| - """ |
716 |
| - if reactor is None: |
717 |
| - from twisted.internet import reactor |
718 |
| - |
719 |
| - if config is None: |
720 |
| - config = default_config(name, parse=True) |
721 |
| - |
722 |
| - config.ldap_enabled = False |
723 |
| - |
724 |
| - if "clock" not in kwargs: |
725 |
| - kwargs["clock"] = MockClock() |
726 |
| - |
727 |
| - if USE_POSTGRES_FOR_TESTS: |
728 |
| - test_db = "synapse_test_%s" % uuid.uuid4().hex |
729 |
| - |
730 |
| - database_config = { |
731 |
| - "name": "psycopg2", |
732 |
| - "args": { |
733 |
| - "database": test_db, |
734 |
| - "host": POSTGRES_HOST, |
735 |
| - "password": POSTGRES_PASSWORD, |
736 |
| - "user": POSTGRES_USER, |
737 |
| - "cp_min": 1, |
738 |
| - "cp_max": 5, |
739 |
| - }, |
740 |
| - } |
741 |
| - else: |
742 |
| - database_config = { |
743 |
| - "name": "sqlite3", |
744 |
| - "args": {"database": ":memory:", "cp_min": 1, "cp_max": 1}, |
745 |
| - } |
746 |
| - |
747 |
| - if "db_txn_limit" in kwargs: |
748 |
| - database_config["txn_limit"] = kwargs["db_txn_limit"] |
749 |
| - |
750 |
| - database = DatabaseConnectionConfig("master", database_config) |
751 |
| - config.database.databases = [database] |
752 |
| - |
753 |
| - db_engine = create_engine(database.config) |
754 |
| - |
755 |
| - # Create the database before we actually try and connect to it, based off |
756 |
| - # the template database we generate in setupdb() |
757 |
| - if isinstance(db_engine, PostgresEngine): |
758 |
| - db_conn = db_engine.module.connect( |
759 |
| - database=POSTGRES_BASE_DB, |
760 |
| - user=POSTGRES_USER, |
761 |
| - host=POSTGRES_HOST, |
762 |
| - password=POSTGRES_PASSWORD, |
763 |
| - ) |
764 |
| - db_conn.autocommit = True |
765 |
| - cur = db_conn.cursor() |
766 |
| - cur.execute("DROP DATABASE IF EXISTS %s;" % (test_db,)) |
767 |
| - cur.execute( |
768 |
| - "CREATE DATABASE %s WITH TEMPLATE %s;" % (test_db, POSTGRES_BASE_DB) |
769 |
| - ) |
770 |
| - cur.close() |
771 |
| - db_conn.close() |
772 |
| - |
773 |
| - hs = homeserver_to_use( |
774 |
| - name, |
775 |
| - config=config, |
776 |
| - version_string="Synapse/tests", |
777 |
| - reactor=reactor, |
778 |
| - ) |
779 |
| - |
780 |
| - # Install @cache_in_self attributes |
781 |
| - for key, val in kwargs.items(): |
782 |
| - setattr(hs, "_" + key, val) |
783 |
| - |
784 |
| - # Mock TLS |
785 |
| - hs.tls_server_context_factory = Mock() |
786 |
| - hs.tls_client_options_factory = Mock() |
787 |
| - |
788 |
| - hs.setup() |
789 |
| - if homeserver_to_use == TestHomeServer: |
790 |
| - hs.setup_background_tasks() |
791 |
| - |
792 |
| - if isinstance(db_engine, PostgresEngine): |
793 |
| - database = hs.get_datastores().databases[0] |
794 |
| - |
795 |
| - # We need to do cleanup on PostgreSQL |
796 |
| - def cleanup(): |
797 |
| - import psycopg2 |
798 |
| - |
799 |
| - # Close all the db pools |
800 |
| - database._db_pool.close() |
801 |
| - |
802 |
| - dropped = False |
803 |
| - |
804 |
| - # Drop the test database |
805 |
| - db_conn = db_engine.module.connect( |
806 |
| - database=POSTGRES_BASE_DB, |
807 |
| - user=POSTGRES_USER, |
808 |
| - host=POSTGRES_HOST, |
809 |
| - password=POSTGRES_PASSWORD, |
810 |
| - ) |
811 |
| - db_conn.autocommit = True |
812 |
| - cur = db_conn.cursor() |
813 |
| - |
814 |
| - # Try a few times to drop the DB. Some things may hold on to the |
815 |
| - # database for a few more seconds due to flakiness, preventing |
816 |
| - # us from dropping it when the test is over. If we can't drop |
817 |
| - # it, warn and move on. |
818 |
| - for _ in range(5): |
819 |
| - try: |
820 |
| - cur.execute("DROP DATABASE IF EXISTS %s;" % (test_db,)) |
821 |
| - db_conn.commit() |
822 |
| - dropped = True |
823 |
| - except psycopg2.OperationalError as e: |
824 |
| - warnings.warn( |
825 |
| - "Couldn't drop old db: " + str(e), category=UserWarning |
826 |
| - ) |
827 |
| - time.sleep(0.5) |
828 |
| - |
829 |
| - cur.close() |
830 |
| - db_conn.close() |
831 |
| - |
832 |
| - if not dropped: |
833 |
| - warnings.warn("Failed to drop old DB.", category=UserWarning) |
834 |
| - |
835 |
| - if not LEAVE_DB: |
836 |
| - # Register the cleanup hook |
837 |
| - cleanup_func(cleanup) |
838 |
| - |
839 |
| - # bcrypt is far too slow to be doing in unit tests |
840 |
| - # Need to let the HS build an auth handler and then mess with it |
841 |
| - # because AuthHandler's constructor requires the HS, so we can't make one |
842 |
| - # beforehand and pass it in to the HS's constructor (chicken / egg) |
843 |
| - async def hash(p): |
844 |
| - return hashlib.md5(p.encode("utf8")).hexdigest() |
845 |
| - |
846 |
| - hs.get_auth_handler().hash = hash |
847 |
| - |
848 |
| - async def validate_hash(p, h): |
849 |
| - return hashlib.md5(p.encode("utf8")).hexdigest() == h |
850 |
| - |
851 |
| - hs.get_auth_handler().validate_hash = validate_hash |
852 |
| - |
853 |
| - # Make the threadpool and database transactions synchronous for testing. |
854 |
| - make_test_homeserver_synchronous(hs) |
855 |
| - |
856 |
| - return hs |
0 commit comments