Skip to content

Commit

Permalink
make the tests pass against the new API
Browse files Browse the repository at this point in the history
this removes some fragility from the tests
  • Loading branch information
glyph committed Dec 11, 2016
1 parent f19151e commit cd75dd8
Showing 1 changed file with 60 additions and 78 deletions.
138 changes: 60 additions & 78 deletions src/twisted/web/test/test_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
from twisted.python.deprecate import getDeprecationWarningString
from incremental import Version
from twisted.web.client import BrowserLikePolicyForHTTPS
from twisted.internet.test.test_endpoints import deterministicResolvingReactor
from twisted.internet.endpoints import HostnameEndpoint
from twisted.web.error import SchemeNotSupported

try:
Expand Down Expand Up @@ -290,29 +292,36 @@ def test_resumeProducing(self):
self._scheduled.pop(0)()
self.assertEqual(expectedResult[:readSize * 2], output.getvalue())


EXAMPLE_COM_IP = '127.0.0.7'
EXAMPLE_NET_IP = '127.0.0.8'
EXAMPLE_ORG_IP = '127.0.0.9'
FOO_LOCAL_IP = '127.0.0.10'
FOO_COM_IP = '127.0.0.11'

class FakeReactorAndConnectMixin:
"""
A test mixin providing a testable C{Reactor} class and a dummy C{connect}
method which allows instances to pretend to be endpoints.
"""
Reactor = MemoryReactorClock

@implementer(IPolicyForHTTPS)
class StubPolicy(object):
"""
A stub policy for HTTPS URIs which allows HTTPS tests to run even if
pyOpenSSL isn't installed.
"""
def creatorForNetloc(self, hostname, port):
"""
Don't actually do anything.
@param hostname: ignored
def createReactor(self):
"""
Create a L{MemoryReactorClock} and give it some hostnames it can
resolve.
"""
mrc = MemoryReactorClock()
drr = deterministicResolvingReactor(mrc, hostMap={
u'example.com': [EXAMPLE_COM_IP],
u'example.net': [EXAMPLE_NET_IP],
u'example.org': [EXAMPLE_ORG_IP],
u'foo': [FOO_LOCAL_IP],
u'foo.com': [FOO_COM_IP],
})

@param port: ignored
"""
# Lots of tests were written expecting MemoryReactorClock and the
# reactor seen by the SUT to be the same object.
drr.tcpClients = mrc.tcpClients
drr.advance = mrc.advance
return drr

class StubEndpoint(object):
"""
Expand All @@ -338,7 +347,7 @@ def buildAgentForWrapperTest(self, reactor):
Return an Agent suitable for use in tests that wrap the Agent and want
both a fake reactor and StubHTTPProtocol.
"""
agent = client.Agent(reactor, self.StubPolicy())
agent = client.Agent(reactor)
_oldGetEndpoint = agent._getEndpoint
agent._getEndpoint = lambda *args: (
self.StubEndpoint(_oldGetEndpoint(*args), self))
Expand Down Expand Up @@ -395,7 +404,7 @@ class HTTPConnectionPoolTests(TestCase, FakeReactorAndConnectMixin):
Tests for the L{HTTPConnectionPool} class.
"""
def setUp(self):
self.fakeReactor = self.Reactor()
self.fakeReactor = self.createReactor()
self.pool = HTTPConnectionPool(self.fakeReactor)
self.pool._factory = DummyFactory
# The retry code path is tested in HTTPConnectionPoolRetryTests:
Expand Down Expand Up @@ -744,7 +753,7 @@ def setUp(self):
"""
Create an L{Agent} wrapped around a fake reactor.
"""
self.reactor = self.Reactor()
self.reactor = self.createReactor()
self.agent = self.makeAgent()


Expand Down Expand Up @@ -845,21 +854,23 @@ def test_connectionFailed(self):
# Cause the connection to be refused
host, port, factory = self.reactor.tcpClients.pop()[:3]
factory.clientConnectionFailed(None, Failure(ConnectionRefusedError()))
return self.assertFailure(result, ConnectionRefusedError)
self.reactor.advance(10)
# ^ https://twistedmatrix.com/trac/ticket/8202
self.failureResultOf(result, ConnectionRefusedError)


def test_connectHTTP(self):
"""
L{Agent._getEndpoint} return a C{TCP4ClientEndpoint} when passed a
scheme of C{'http'}.
L{Agent._getEndpoint} return a C{HostnameEndpoint} when passed a scheme
of C{'http'}.
"""
expectedHost = b'example.com'
expectedPort = 1234
endpoint = self.agent._getEndpoint(URI.fromBytes(
b'http://' + expectedHost + b":" + intToBytes(expectedPort)))
self.assertEqual(endpoint._host, "example.com")
self.assertEqual(endpoint._hostStr, "example.com")
self.assertEqual(endpoint._port, expectedPort)
self.assertIsInstance(endpoint, TCP4ClientEndpoint)
self.assertIsInstance(endpoint, HostnameEndpoint)


def test_nonDecodableURI(self):
Expand All @@ -879,33 +890,6 @@ def test_nonDecodableURI(self):
"decodable.").format(reprout=repr(uri.host)))


def test_connectHTTPSCustomContextFactory(self):
"""
If a context factory is passed to L{Agent.__init__} it will be used to
determine the SSL parameters for HTTPS requests. When an HTTPS request
is made, the hostname and port number of the request URL will be passed
to the context factory's C{getContext} method. The resulting context
object will be used to establish the SSL connection.
"""
expectedHost = b'example.org'
expectedPort = 20443
expectedContext = object()

contextArgs = []
class StubWebContextFactory(object):
def getContext(self, hostname, port):
contextArgs.append((hostname, port))
return expectedContext

agent = client.Agent(self.reactor, StubWebContextFactory())
endpoint = agent._getEndpoint(URI.fromBytes(
b'https://' + expectedHost + b":" + intToBytes(expectedPort)))
contextFactory = endpoint._sslContextFactory
context = contextFactory.getContext()
self.assertEqual(context, expectedContext)
self.assertEqual(contextArgs, [(expectedHost, expectedPort)])


def test_hostProvided(self):
"""
If L{None} is passed to L{Agent.request} for the C{headers} parameter,
Expand Down Expand Up @@ -1052,14 +1036,14 @@ def test_connectTimeout(self):
self.assertEqual(5, timeout)


def test_connectSSLTimeout(self):
def test_connectTimeoutHTTPS(self):
"""
L{Agent} takes a C{connectTimeout} argument which is forwarded to the
following C{connectSSL} call.
following C{connectTCP} call.
"""
agent = client.Agent(self.reactor, self.StubPolicy(), connectTimeout=5)
agent = client.Agent(self.reactor, connectTimeout=5)
agent.request(b'GET', b'https://foo/')
timeout = self.reactor.sslClients.pop()[4]
timeout = self.reactor.tcpClients.pop()[3]
self.assertEqual(5, timeout)


Expand All @@ -1079,10 +1063,9 @@ def test_bindAddressSSL(self):
L{Agent} takes a C{bindAddress} argument which is forwarded to the
following C{connectSSL} call.
"""
agent = client.Agent(self.reactor, self.StubPolicy(),
bindAddress='192.168.0.1')
agent = client.Agent(self.reactor, bindAddress='192.168.0.1')
agent.request(b'GET', b'https://foo/')
address = self.reactor.sslClients.pop()[5]
address = self.reactor.tcpClients.pop()[4]
self.assertEqual('192.168.0.1', address)


Expand Down Expand Up @@ -1198,7 +1181,7 @@ def makeEndpoint(self, host=b'example.com', port=443):
@return: An endpoint of an L{Agent} constructed according to args.
@rtype: L{SSL4ClientEndpoint}
"""
return client.Agent(self.Reactor())._getEndpoint(
return client.Agent(self.createReactor())._getEndpoint(
URI.fromBytes(b'https://' + host + b":" + intToBytes(port) + b"/"))


Expand All @@ -1207,15 +1190,18 @@ def test_endpointType(self):
L{Agent._getEndpoint} return a L{SSL4ClientEndpoint} when passed a
scheme of C{'https'}.
"""
self.assertIsInstance(self.makeEndpoint(), SSL4ClientEndpoint)
from twisted.internet.endpoints import _WrapperEndpoint
endpoint = self.makeEndpoint()
self.assertIsInstance(endpoint, _WrapperEndpoint)
self.assertIsInstance(endpoint._wrappedEndpoint, HostnameEndpoint)


def test_hostArgumentIsRespected(self):
"""
If a host is passed, the endpoint respects it.
"""
endpoint = self.makeEndpoint(host=b"example.com")
self.assertEqual(endpoint._host, "example.com")
self.assertEqual(endpoint._wrappedEndpoint._hostStr, "example.com")


def test_portArgumentIsRespected(self):
Expand All @@ -1224,15 +1210,15 @@ def test_portArgumentIsRespected(self):
"""
expectedPort = 4321
endpoint = self.makeEndpoint(port=expectedPort)
self.assertEqual(endpoint._port, expectedPort)
self.assertEqual(endpoint._wrappedEndpoint._port, expectedPort)


def test_contextFactoryType(self):
"""
L{Agent} wraps its connection creator creator and uses modern TLS APIs.
"""
endpoint = self.makeEndpoint()
contextFactory = endpoint._sslContextFactory
contextFactory = endpoint._wrapperFactory(None)._connectionCreator
self.assertIsInstance(contextFactory, ClientTLSOptions)
self.assertEqual(contextFactory._hostname, u"example.com")

Expand Down Expand Up @@ -1301,16 +1287,12 @@ def creatorForNetloc(self, hostname, port):
return JustEnoughCreator(hostname, port)

expectedCreatorCreator = StubBrowserLikePolicyForHTTPS()
reactor = self.Reactor()
reactor = self.createReactor()
agent = client.Agent(reactor, expectedCreatorCreator)
endpoint = agent._getEndpoint(URI.fromBytes(
b'https://' + expectedHost + b":" + intToBytes(expectedPort)))
endpoint.connect(Factory.forProtocol(Protocol))
passedFactory = reactor.sslClients[-1][2]
passedContextFactory = reactor.sslClients[-1][3]
tlsFactory = TLSMemoryBIOFactory(
passedContextFactory, True, passedFactory
)
tlsFactory = reactor.tcpClients[-1][2]
tlsProtocol = tlsFactory.buildProtocol(None)
tlsProtocol.makeConnection(StringTransport())
tls = contextArgs[0][0]
Expand Down Expand Up @@ -1803,7 +1785,7 @@ def makeAgent(self):


def setUp(self):
self.reactor = self.Reactor()
self.reactor = self.createReactor()


def test_emptyCookieJarRequest(self):
Expand Down Expand Up @@ -1968,7 +1950,7 @@ def setUp(self):
"""
Create an L{Agent} wrapped around a fake reactor.
"""
self.reactor = self.Reactor()
self.reactor = self.createReactor()
self.agent = self.buildAgentForWrapperTest(self.reactor)


Expand Down Expand Up @@ -2114,7 +2096,7 @@ def setUp(self):
"""
Create an L{Agent} wrapped around a fake reactor.
"""
self.reactor = self.Reactor()
self.reactor = self.createReactor()
agent = self.buildAgentForWrapperTest(self.reactor)
self.agent = client.ContentDecoderAgent(
agent, [(b"gzip", client.GzipDecoder)])
Expand Down Expand Up @@ -2311,7 +2293,7 @@ def makeAgent(self):


def setUp(self):
self.reactor = self.Reactor()
self.reactor = self.createReactor()
self.agent = client.ProxyAgent(
TCP4ClientEndpoint(self.reactor, "bar", 5678), self.reactor)
oldEndpoint = self.agent._proxyEndpoint
Expand Down Expand Up @@ -2421,7 +2403,7 @@ def _testRedirectDefault(self, code):
self.agent.request(b'GET', b'http://example.com/foo')

host, port = self.reactor.tcpClients.pop()[:2]
self.assertEqual("example.com", host)
self.assertEqual(EXAMPLE_COM_IP, host)
self.assertEqual(80, port)

req, res = self.protocol.requests.pop()
Expand All @@ -2435,8 +2417,8 @@ def _testRedirectDefault(self, code):
self.assertEqual(b'GET', req2.method)
self.assertEqual(b'/bar', req2.uri)

host, port = self.reactor.sslClients.pop()[:2]
self.assertEqual("example.com", host)
host, port = self.reactor.tcpClients.pop()[:2]
self.assertEqual(EXAMPLE_COM_IP, host)
self.assertEqual(443, port)


Expand Down Expand Up @@ -2690,7 +2672,7 @@ def makeAgent(self):


def setUp(self):
self.reactor = self.Reactor()
self.reactor = self.createReactor()
self.agent = self.makeAgent()


Expand Down Expand Up @@ -2729,7 +2711,7 @@ def makeAgent(self):


def setUp(self):
self.reactor = self.Reactor()
self.reactor = self.createReactor()
self.agent = self.makeAgent()


Expand Down

0 comments on commit cd75dd8

Please sign in to comment.