From 05282b3f35eb058d9463e8647ae59833b7ff329e Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Fri, 20 Oct 2023 08:20:32 -0400 Subject: [PATCH 01/10] Combine duplicated code. --- tests/http/__init__.py | 28 ++++++++- .../test_matrix_federation_agent.py | 58 +++++++------------ tests/http/test_proxyagent.py | 44 ++++---------- tests/replication/test_multi_media_repo.py | 52 +++++------------ 4 files changed, 71 insertions(+), 111 deletions(-) diff --git a/tests/http/__init__.py b/tests/http/__init__.py index 528cdee34b8b..39fb35e54fa8 100644 --- a/tests/http/__init__.py +++ b/tests/http/__init__.py @@ -20,9 +20,12 @@ from OpenSSL import SSL from OpenSSL.SSL import Connection from twisted.internet.address import IPv4Address -from twisted.internet.interfaces import IOpenSSLServerConnectionCreator +from twisted.internet.interfaces import ( + IOpenSSLServerConnectionCreator, + IProtocolFactory, +) from twisted.internet.ssl import Certificate, trustRootFromCertificates -from twisted.protocols.tls import TLSMemoryBIOProtocol +from twisted.protocols.tls import TLSMemoryBIOFactory, TLSMemoryBIOProtocol from twisted.web.client import BrowserLikePolicyForHTTPS # noqa: F401 from twisted.web.iweb import IPolicyForHTTPS # noqa: F401 @@ -153,6 +156,27 @@ def serverConnectionForTLS(self, tlsProtocol: TLSMemoryBIOProtocol) -> Connectio return Connection(ctx, None) +def wrap_server_factory_for_tls( + factory: IProtocolFactory, sanlist: List[bytes] +) -> TLSMemoryBIOFactory: + """Wrap an existing Protocol Factory with a test TLSMemoryBIOFactory + + The resultant factory will create a TLS server which presents a certificate + signed by our test CA, valid for the domains in `sanlist` + + Args: + factory: protocol factory to wrap + sanlist: list of domains the cert should be valid for + + Returns: + interfaces.IProtocolFactory + """ + connection_creator = TestServerTLSConnectionFactory(sanlist=sanlist) + return TLSMemoryBIOFactory( + connection_creator, isClient=False, wrappedFactory=factory + ) + + # A dummy address, useful for tests that use FakeTransport and don't care about where # packets are going to/coming from. dummy_address = IPv4Address("TCP", "127.0.0.1", 80) diff --git a/tests/http/federation/test_matrix_federation_agent.py b/tests/http/federation/test_matrix_federation_agent.py index 9f63fa6fa815..9f6f403367ba 100644 --- a/tests/http/federation/test_matrix_federation_agent.py +++ b/tests/http/federation/test_matrix_federation_agent.py @@ -31,7 +31,7 @@ IProtocolFactory, ) from twisted.internet.protocol import Factory, Protocol -from twisted.protocols.tls import TLSMemoryBIOFactory, TLSMemoryBIOProtocol +from twisted.protocols.tls import TLSMemoryBIOProtocol from twisted.web._newclient import ResponseNeverReceived from twisted.web.client import Agent from twisted.web.http import HTTPChannel, Request @@ -57,11 +57,7 @@ from synapse.util.caches.ttlcache import TTLCache from tests import unittest -from tests.http import ( - TestServerTLSConnectionFactory, - dummy_address, - get_test_ca_cert_file, -) +from tests.http import dummy_address, get_test_ca_cert_file, wrap_server_factory_for_tls from tests.server import FakeTransport, ThreadedMemoryReactorClock from tests.utils import checked_cast, default_config @@ -125,7 +121,17 @@ def _make_connection( # build the test server server_factory = _get_test_protocol_factory() if ssl: - server_factory = _wrap_server_factory_for_tls(server_factory, tls_sanlist) + server_factory = wrap_server_factory_for_tls( + server_factory, + tls_sanlist + or [ + b"DNS:testserv", + b"DNS:target-server", + b"DNS:xn--bcher-kva.com", + b"IP:1.2.3.4", + b"IP:::1", + ], + ) server_protocol = server_factory.buildProtocol(dummy_address) assert server_protocol is not None @@ -435,8 +441,15 @@ def _do_get_via_proxy( request.finish() # now we make another test server to act as the upstream HTTP server. - server_ssl_protocol = _wrap_server_factory_for_tls( - _get_test_protocol_factory() + server_ssl_protocol = wrap_server_factory_for_tls( + _get_test_protocol_factory(), + sanlist=[ + b"DNS:testserv", + b"DNS:target-server", + b"DNS:xn--bcher-kva.com", + b"IP:1.2.3.4", + b"IP:::1", + ], ).buildProtocol(dummy_address) # Tell the HTTP server to send outgoing traffic back via the proxy's transport. @@ -1786,33 +1799,6 @@ def _check_logcontext(context: LoggingContextOrSentinel) -> None: raise AssertionError("Expected logcontext %s but was %s" % (context, current)) -def _wrap_server_factory_for_tls( - factory: IProtocolFactory, sanlist: Optional[List[bytes]] = None -) -> TLSMemoryBIOFactory: - """Wrap an existing Protocol Factory with a test TLSMemoryBIOFactory - The resultant factory will create a TLS server which presents a certificate - signed by our test CA, valid for the domains in `sanlist` - Args: - factory: protocol factory to wrap - sanlist: list of domains the cert should be valid for - Returns: - interfaces.IProtocolFactory - """ - if sanlist is None: - sanlist = [ - b"DNS:testserv", - b"DNS:target-server", - b"DNS:xn--bcher-kva.com", - b"IP:1.2.3.4", - b"IP:::1", - ] - - connection_creator = TestServerTLSConnectionFactory(sanlist=sanlist) - return TLSMemoryBIOFactory( - connection_creator, isClient=False, wrappedFactory=factory - ) - - def _get_test_protocol_factory() -> IProtocolFactory: """Get a protocol Factory which will build an HTTPChannel Returns: diff --git a/tests/http/test_proxyagent.py b/tests/http/test_proxyagent.py index 8164b0b78e31..e8d3c3c274c3 100644 --- a/tests/http/test_proxyagent.py +++ b/tests/http/test_proxyagent.py @@ -29,18 +29,14 @@ ) from twisted.internet.interfaces import IProtocol, IProtocolFactory from twisted.internet.protocol import Factory, Protocol -from twisted.protocols.tls import TLSMemoryBIOFactory, TLSMemoryBIOProtocol +from twisted.protocols.tls import TLSMemoryBIOProtocol from twisted.web.http import HTTPChannel from synapse.http.client import BlocklistingReactorWrapper from synapse.http.connectproxyclient import BasicProxyCredentials from synapse.http.proxyagent import ProxyAgent, parse_proxy -from tests.http import ( - TestServerTLSConnectionFactory, - dummy_address, - get_test_https_policy, -) +from tests.http import dummy_address, get_test_https_policy, wrap_server_factory_for_tls from tests.server import FakeTransport, ThreadedMemoryReactorClock from tests.unittest import TestCase from tests.utils import checked_cast @@ -251,7 +247,9 @@ def _make_connection( the server Protocol returned by server_factory """ if ssl: - server_factory = _wrap_server_factory_for_tls(server_factory, tls_sanlist) + server_factory = wrap_server_factory_for_tls( + server_factory, tls_sanlist or [b"DNS:test.com"] + ) server_protocol = server_factory.buildProtocol(dummy_address) assert server_protocol is not None @@ -618,8 +616,8 @@ def _do_https_request_via_proxy( request.finish() # now we make another test server to act as the upstream HTTP server. - server_ssl_protocol = _wrap_server_factory_for_tls( - _get_test_protocol_factory() + server_ssl_protocol = wrap_server_factory_for_tls( + _get_test_protocol_factory(), sanlist=[b"DNS:test.com"] ).buildProtocol(dummy_address) # Tell the HTTP server to send outgoing traffic back via the proxy's transport. @@ -785,7 +783,9 @@ def test_https_request_via_uppercase_proxy_with_blocklist(self) -> None: request.finish() # now we can replace the proxy channel with a new, SSL-wrapped HTTP channel - ssl_factory = _wrap_server_factory_for_tls(_get_test_protocol_factory()) + ssl_factory = wrap_server_factory_for_tls( + _get_test_protocol_factory(), sanlist=[b"DNS:test.com"] + ) ssl_protocol = ssl_factory.buildProtocol(dummy_address) assert isinstance(ssl_protocol, TLSMemoryBIOProtocol) http_server = ssl_protocol.wrappedProtocol @@ -849,30 +849,6 @@ def test_proxy_with_https_scheme(self) -> None: self.assertEqual(proxy_ep._wrappedEndpoint._port, 8888) -def _wrap_server_factory_for_tls( - factory: IProtocolFactory, sanlist: Optional[List[bytes]] = None -) -> TLSMemoryBIOFactory: - """Wrap an existing Protocol Factory with a test TLSMemoryBIOFactory - - The resultant factory will create a TLS server which presents a certificate - signed by our test CA, valid for the domains in `sanlist` - - Args: - factory: protocol factory to wrap - sanlist: list of domains the cert should be valid for - - Returns: - interfaces.IProtocolFactory - """ - if sanlist is None: - sanlist = [b"DNS:test.com"] - - connection_creator = TestServerTLSConnectionFactory(sanlist=sanlist) - return TLSMemoryBIOFactory( - connection_creator, isClient=False, wrappedFactory=factory - ) - - def _get_test_protocol_factory() -> IProtocolFactory: """Get a protocol Factory which will build an HTTPChannel diff --git a/tests/replication/test_multi_media_repo.py b/tests/replication/test_multi_media_repo.py index b230a6c361b4..611c95b8e876 100644 --- a/tests/replication/test_multi_media_repo.py +++ b/tests/replication/test_multi_media_repo.py @@ -15,9 +15,7 @@ import os from typing import Any, Optional, Tuple -from twisted.internet.interfaces import IOpenSSLServerConnectionCreator from twisted.internet.protocol import Factory -from twisted.protocols.tls import TLSMemoryBIOFactory, TLSMemoryBIOProtocol from twisted.test.proto_helpers import MemoryReactor from twisted.web.http import HTTPChannel from twisted.web.server import Request @@ -27,7 +25,11 @@ from synapse.server import HomeServer from synapse.util import Clock -from tests.http import TestServerTLSConnectionFactory, get_test_ca_cert_file +from tests.http import ( + TestServerTLSConnectionFactory, + get_test_ca_cert_file, + wrap_server_factory_for_tls, +) from tests.replication._base import BaseMultiWorkerStreamTestCase from tests.server import FakeChannel, FakeTransport, make_request from tests.test_utils import SMALL_PNG @@ -94,7 +96,13 @@ def _get_media_req( (host, port, client_factory, _timeout, _bindAddress) = clients.pop() # build the test server - server_tls_protocol = _build_test_server(get_connection_factory()) + server_factory = Factory.forProtocol(HTTPChannel) + # Request.finish expects the factory to have a 'log' method. + server_factory.log = _log_request + + server_tls_protocol = wrap_server_factory_for_tls( + server_factory, sanlist=[b"DNS:example.com"] + ).buildProtocol(None) # now, tell the client protocol factory to build the client protocol (it will be a # _WrappingProtocol, around a TLSMemoryBIOProtocol, around an @@ -114,7 +122,7 @@ def _get_media_req( ) # fish the test server back out of the server-side TLS protocol. - http_server: HTTPChannel = server_tls_protocol.wrappedProtocol # type: ignore[assignment] + http_server: HTTPChannel = server_tls_protocol.wrappedProtocol # give the reactor a pump to get the TLS juices flowing. self.reactor.pump((0.1,)) @@ -240,40 +248,6 @@ def _count_remote_thumbnails(self) -> int: return sum(len(files) for _, _, files in os.walk(path)) -def get_connection_factory() -> TestServerTLSConnectionFactory: - # this needs to happen once, but not until we are ready to run the first test - global test_server_connection_factory - if test_server_connection_factory is None: - test_server_connection_factory = TestServerTLSConnectionFactory( - sanlist=[b"DNS:example.com"] - ) - return test_server_connection_factory - - -def _build_test_server( - connection_creator: IOpenSSLServerConnectionCreator, -) -> TLSMemoryBIOProtocol: - """Construct a test server - - This builds an HTTP channel, wrapped with a TLSMemoryBIOProtocol - - Args: - connection_creator: thing to build SSL connections - - Returns: - TLSMemoryBIOProtocol - """ - server_factory = Factory.forProtocol(HTTPChannel) - # Request.finish expects the factory to have a 'log' method. - server_factory.log = _log_request - - server_tls_factory = TLSMemoryBIOFactory( - connection_creator, isClient=False, wrappedFactory=server_factory - ) - - return server_tls_factory.buildProtocol(None) - - def _log_request(request: Request) -> None: """Implements Factory.log, which is expected by Request.finish""" logger.info("Completed request %s", request) From c6afddeb711e4d963287b0b1daaadd9d90724b04 Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Thu, 19 Oct 2023 16:18:00 -0400 Subject: [PATCH 02/10] Fix tests for Twisted > 23.8.0. --- tests/http/__init__.py | 17 +++++++++++++---- .../federation/test_matrix_federation_agent.py | 2 ++ tests/http/test_proxyagent.py | 6 +++--- tests/replication/test_multi_media_repo.py | 2 +- tests/server.py | 14 +++++++++++++- 5 files changed, 32 insertions(+), 9 deletions(-) diff --git a/tests/http/__init__.py b/tests/http/__init__.py index 39fb35e54fa8..d5306e7ee022 100644 --- a/tests/http/__init__.py +++ b/tests/http/__init__.py @@ -15,14 +15,17 @@ import subprocess from typing import List +from incremental import Version from zope.interface import implementer +import twisted from OpenSSL import SSL from OpenSSL.SSL import Connection from twisted.internet.address import IPv4Address from twisted.internet.interfaces import ( IOpenSSLServerConnectionCreator, IProtocolFactory, + IReactorTime, ) from twisted.internet.ssl import Certificate, trustRootFromCertificates from twisted.protocols.tls import TLSMemoryBIOFactory, TLSMemoryBIOProtocol @@ -157,7 +160,7 @@ def serverConnectionForTLS(self, tlsProtocol: TLSMemoryBIOProtocol) -> Connectio def wrap_server_factory_for_tls( - factory: IProtocolFactory, sanlist: List[bytes] + factory: IProtocolFactory, clock: IReactorTime, sanlist: List[bytes] ) -> TLSMemoryBIOFactory: """Wrap an existing Protocol Factory with a test TLSMemoryBIOFactory @@ -172,9 +175,15 @@ def wrap_server_factory_for_tls( interfaces.IProtocolFactory """ connection_creator = TestServerTLSConnectionFactory(sanlist=sanlist) - return TLSMemoryBIOFactory( - connection_creator, isClient=False, wrappedFactory=factory - ) + # Twisted > 23.8.0 has a different API that accepts a clock. + if twisted.version <= Version("Twisted", 23, 8, 0): + return TLSMemoryBIOFactory( + connection_creator, isClient=False, wrappedFactory=factory + ) + else: + return TLSMemoryBIOFactory( + connection_creator, isClient=False, wrappedFactory=factory, clock=clock # type: ignore[call-arg] + ) # A dummy address, useful for tests that use FakeTransport and don't care about where diff --git a/tests/http/federation/test_matrix_federation_agent.py b/tests/http/federation/test_matrix_federation_agent.py index 9f6f403367ba..0f623ae50b11 100644 --- a/tests/http/federation/test_matrix_federation_agent.py +++ b/tests/http/federation/test_matrix_federation_agent.py @@ -123,6 +123,7 @@ def _make_connection( if ssl: server_factory = wrap_server_factory_for_tls( server_factory, + self.reactor, tls_sanlist or [ b"DNS:testserv", @@ -443,6 +444,7 @@ def _do_get_via_proxy( # now we make another test server to act as the upstream HTTP server. server_ssl_protocol = wrap_server_factory_for_tls( _get_test_protocol_factory(), + self.reactor, sanlist=[ b"DNS:testserv", b"DNS:target-server", diff --git a/tests/http/test_proxyagent.py b/tests/http/test_proxyagent.py index e8d3c3c274c3..6cc532c3f239 100644 --- a/tests/http/test_proxyagent.py +++ b/tests/http/test_proxyagent.py @@ -248,7 +248,7 @@ def _make_connection( """ if ssl: server_factory = wrap_server_factory_for_tls( - server_factory, tls_sanlist or [b"DNS:test.com"] + server_factory, self.reactor, tls_sanlist or [b"DNS:test.com"] ) server_protocol = server_factory.buildProtocol(dummy_address) @@ -617,7 +617,7 @@ def _do_https_request_via_proxy( # now we make another test server to act as the upstream HTTP server. server_ssl_protocol = wrap_server_factory_for_tls( - _get_test_protocol_factory(), sanlist=[b"DNS:test.com"] + _get_test_protocol_factory(), self.reactor, sanlist=[b"DNS:test.com"] ).buildProtocol(dummy_address) # Tell the HTTP server to send outgoing traffic back via the proxy's transport. @@ -784,7 +784,7 @@ def test_https_request_via_uppercase_proxy_with_blocklist(self) -> None: # now we can replace the proxy channel with a new, SSL-wrapped HTTP channel ssl_factory = wrap_server_factory_for_tls( - _get_test_protocol_factory(), sanlist=[b"DNS:test.com"] + _get_test_protocol_factory(), self.reactor, sanlist=[b"DNS:test.com"] ) ssl_protocol = ssl_factory.buildProtocol(dummy_address) assert isinstance(ssl_protocol, TLSMemoryBIOProtocol) diff --git a/tests/replication/test_multi_media_repo.py b/tests/replication/test_multi_media_repo.py index 611c95b8e876..1e9994cc0bc7 100644 --- a/tests/replication/test_multi_media_repo.py +++ b/tests/replication/test_multi_media_repo.py @@ -101,7 +101,7 @@ def _get_media_req( server_factory.log = _log_request server_tls_protocol = wrap_server_factory_for_tls( - server_factory, sanlist=[b"DNS:example.com"] + server_factory, self.reactor, sanlist=[b"DNS:example.com"] ).buildProtocol(None) # now, tell the client protocol factory to build the client protocol (it will be a diff --git a/tests/server.py b/tests/server.py index 08633fe640f4..717c58e25db4 100644 --- a/tests/server.py +++ b/tests/server.py @@ -40,7 +40,7 @@ Union, cast, ) -from unittest.mock import Mock +from unittest.mock import Mock, patch import attr from typing_extensions import ParamSpec @@ -474,6 +474,18 @@ def getHostByName( return fail(DNSLookupError("OH NO: unknown %s" % (name,))) return succeed(lookups[name]) + # In order for the TLS protocols to use the proper we need to patch + # _get_default_clock. + # + # This is *super* dirty since we never unpatch and rely on the next test + # to patch over us. + # + # Use create=True for backwards compatibilty with Twisted <= 23.8.0. + self._tls_clock_patcher = patch( + "twisted.protocols.tls._get_default_clock", return_value=self, create=True + ) + self._tls_clock_patcher.start() + self.nameResolver = SimpleResolverComplexifier(FakeResolver()) super().__init__() From f4efd04c45f0d05d5471964ef9f75a6ce407eae3 Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Fri, 20 Oct 2023 09:42:56 -0400 Subject: [PATCH 03/10] Newsfragment --- changelog.d/16528.misc | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/16528.misc diff --git a/changelog.d/16528.misc b/changelog.d/16528.misc new file mode 100644 index 000000000000..32954ea675e5 --- /dev/null +++ b/changelog.d/16528.misc @@ -0,0 +1 @@ +Fix running unit tests on Twisted trunk. From 69d0181b014845209e4a9712ee37c2a735866010 Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Mon, 23 Oct 2023 09:22:47 -0400 Subject: [PATCH 04/10] Clarify comment. --- tests/server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/server.py b/tests/server.py index 717c58e25db4..d1d9e704af03 100644 --- a/tests/server.py +++ b/tests/server.py @@ -474,7 +474,7 @@ def getHostByName( return fail(DNSLookupError("OH NO: unknown %s" % (name,))) return succeed(lookups[name]) - # In order for the TLS protocols to use the proper we need to patch + # In order for the TLS protocols to use the proper reactor's clock we need to patch # _get_default_clock. # # This is *super* dirty since we never unpatch and rely on the next test From 5dcaea64635b89953e66bb9e3ed9537cf178f1b1 Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Mon, 23 Oct 2023 15:57:28 -0400 Subject: [PATCH 05/10] TEMP: Test w/o patch. --- tests/server.py | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/tests/server.py b/tests/server.py index d1d9e704af03..08633fe640f4 100644 --- a/tests/server.py +++ b/tests/server.py @@ -40,7 +40,7 @@ Union, cast, ) -from unittest.mock import Mock, patch +from unittest.mock import Mock import attr from typing_extensions import ParamSpec @@ -474,18 +474,6 @@ def getHostByName( return fail(DNSLookupError("OH NO: unknown %s" % (name,))) return succeed(lookups[name]) - # In order for the TLS protocols to use the proper reactor's clock we need to patch - # _get_default_clock. - # - # This is *super* dirty since we never unpatch and rely on the next test - # to patch over us. - # - # Use create=True for backwards compatibilty with Twisted <= 23.8.0. - self._tls_clock_patcher = patch( - "twisted.protocols.tls._get_default_clock", return_value=self, create=True - ) - self._tls_clock_patcher.start() - self.nameResolver = SimpleResolverComplexifier(FakeResolver()) super().__init__() From 79c76e6c70ebbc64acd0ee833923d93303cdff8b Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Mon, 23 Oct 2023 16:22:36 -0400 Subject: [PATCH 06/10] Revert "TEMP: Test w/o patch." This reverts commit 5dcaea64635b89953e66bb9e3ed9537cf178f1b1. --- tests/server.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tests/server.py b/tests/server.py index 08633fe640f4..d1d9e704af03 100644 --- a/tests/server.py +++ b/tests/server.py @@ -40,7 +40,7 @@ Union, cast, ) -from unittest.mock import Mock +from unittest.mock import Mock, patch import attr from typing_extensions import ParamSpec @@ -474,6 +474,18 @@ def getHostByName( return fail(DNSLookupError("OH NO: unknown %s" % (name,))) return succeed(lookups[name]) + # In order for the TLS protocols to use the proper reactor's clock we need to patch + # _get_default_clock. + # + # This is *super* dirty since we never unpatch and rely on the next test + # to patch over us. + # + # Use create=True for backwards compatibilty with Twisted <= 23.8.0. + self._tls_clock_patcher = patch( + "twisted.protocols.tls._get_default_clock", return_value=self, create=True + ) + self._tls_clock_patcher.start() + self.nameResolver = SimpleResolverComplexifier(FakeResolver()) super().__init__() From 3467806630554212df83a477ae1b7651a6de8691 Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Tue, 24 Oct 2023 10:01:10 -0400 Subject: [PATCH 07/10] Fix tests? --- tests/server.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/tests/server.py b/tests/server.py index d1d9e704af03..92b2c697d420 100644 --- a/tests/server.py +++ b/tests/server.py @@ -43,9 +43,11 @@ from unittest.mock import Mock, patch import attr +from incremental import Version from typing_extensions import ParamSpec from zope.interface import implementer +import twisted from twisted.internet import address, tcp, threads, udp from twisted.internet._resolver import SimpleResolverComplexifier from twisted.internet.defer import Deferred, fail, maybeDeferred, succeed @@ -474,17 +476,18 @@ def getHostByName( return fail(DNSLookupError("OH NO: unknown %s" % (name,))) return succeed(lookups[name]) - # In order for the TLS protocols to use the proper reactor's clock we need to patch - # _get_default_clock. + # In order for the TLS protocols to use the proper reactor's clock, patch + # _get_default_clock on newer Twisted versions. # - # This is *super* dirty since we never unpatch and rely on the next test - # to patch over us. + # This is *super* dirty since it is never stopped and relies on the next + # test to patch over it. # # Use create=True for backwards compatibilty with Twisted <= 23.8.0. - self._tls_clock_patcher = patch( - "twisted.protocols.tls._get_default_clock", return_value=self, create=True - ) - self._tls_clock_patcher.start() + if twisted.version > Version("Twisted", 23, 8, 0): + self._tls_clock_patcher = patch( + "twisted.protocols.tls._get_default_clock", return_value=self + ) + self._tls_clock_patcher.start() self.nameResolver = SimpleResolverComplexifier(FakeResolver()) super().__init__() From 01d1e83bf3852281edb5785a669d1f5302553fb8 Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Tue, 24 Oct 2023 12:47:54 -0400 Subject: [PATCH 08/10] Another try. --- tests/server.py | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/tests/server.py b/tests/server.py index 92b2c697d420..b6d7d20a8a08 100644 --- a/tests/server.py +++ b/tests/server.py @@ -476,18 +476,15 @@ def getHostByName( return fail(DNSLookupError("OH NO: unknown %s" % (name,))) return succeed(lookups[name]) - # In order for the TLS protocols to use the proper reactor's clock, patch - # _get_default_clock on newer Twisted versions. + # In order for the TLS protocol tests to work, modify _get_default_clock + # on newer Twisted versions to use the test reactor's clock. # - # This is *super* dirty since it is never stopped and relies on the next - # test to patch over it. - # - # Use create=True for backwards compatibilty with Twisted <= 23.8.0. + # This is *super* dirty since it is never undone and relies on the next + # test to overwrite it. if twisted.version > Version("Twisted", 23, 8, 0): - self._tls_clock_patcher = patch( - "twisted.protocols.tls._get_default_clock", return_value=self - ) - self._tls_clock_patcher.start() + from twisted.protocols import tls + + tls._get_default_clock = lambda: self self.nameResolver = SimpleResolverComplexifier(FakeResolver()) super().__init__() From 6dec5c39758a8dda54fad88f2ee0b371d7ebc3b1 Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Tue, 24 Oct 2023 12:56:05 -0400 Subject: [PATCH 09/10] Lint --- tests/server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/server.py b/tests/server.py index b6d7d20a8a08..c8342db399ab 100644 --- a/tests/server.py +++ b/tests/server.py @@ -40,7 +40,7 @@ Union, cast, ) -from unittest.mock import Mock, patch +from unittest.mock import Mock import attr from incremental import Version From 412d5937c0863d6366c3c7ea8acc296ea1bd0c24 Mon Sep 17 00:00:00 2001 From: Patrick Cloke Date: Tue, 24 Oct 2023 13:22:29 -0400 Subject: [PATCH 10/10] Lint --- tests/server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/server.py b/tests/server.py index c8342db399ab..cfb0fb823b07 100644 --- a/tests/server.py +++ b/tests/server.py @@ -484,7 +484,7 @@ def getHostByName( if twisted.version > Version("Twisted", 23, 8, 0): from twisted.protocols import tls - tls._get_default_clock = lambda: self + tls._get_default_clock = lambda: self # type: ignore[attr-defined] self.nameResolver = SimpleResolverComplexifier(FakeResolver()) super().__init__()