1
# Copyright (c) 2009 Twisted Matrix Laboratories.
2
# See LICENSE for details.
5
Tests for L{twisted.internet.base}.
9
from Queue import Queue
11
from zope.interface import implements
13
from twisted.python.threadpool import ThreadPool
14
from twisted.python.util import setIDFunction
15
from twisted.internet.interfaces import IReactorTime, IReactorThreads
16
from twisted.internet.error import DNSLookupError
17
from twisted.internet.base import ThreadedResolver, DelayedCall
18
from twisted.internet.task import Clock
19
from twisted.trial.unittest import TestCase
22
class FakeReactor(object):
24
A fake reactor implementation which just supports enough reactor APIs for
27
implements(IReactorTime, IReactorThreads)
31
self.callLater = self._clock.callLater
33
self._threadpool = ThreadPool()
34
self._threadpool.start()
35
self.getThreadPool = lambda: self._threadpool
37
self._threadCalls = Queue()
40
def callFromThread(self, f, *args, **kwargs):
41
self._threadCalls.put((f, args, kwargs))
44
def _runThreadCalls(self):
45
f, args, kwargs = self._threadCalls.get()
50
self._threadpool.stop()
54
class ThreadedResolverTests(TestCase):
56
Tests for L{ThreadedResolver}.
58
def test_success(self):
60
L{ThreadedResolver.getHostByName} returns a L{Deferred} which fires
61
with the value returned by the call to L{socket.gethostbyname} in the
62
threadpool of the reactor passed to L{ThreadedResolver.__init__}.
65
name = "foo.bar.example.com"
68
reactor = FakeReactor()
69
self.addCleanup(reactor._stop)
73
def fakeGetHostByName(name):
77
self.patch(socket, 'gethostbyname', fakeGetHostByName)
79
resolver = ThreadedResolver(reactor)
80
d = resolver.getHostByName(name, (timeout,))
81
d.addCallback(resolvedTo.append)
83
reactor._runThreadCalls()
85
self.assertEqual(lookedUp, [name])
86
self.assertEqual(resolvedTo, [ip])
88
# Make sure that any timeout-related stuff gets cleaned up.
89
reactor._clock.advance(timeout + 1)
90
self.assertEqual(reactor._clock.calls, [])
93
def test_failure(self):
95
L{ThreadedResolver.getHostByName} returns a L{Deferred} which fires a
96
L{Failure} if the call to L{socket.gethostbyname} raises an exception.
100
reactor = FakeReactor()
101
self.addCleanup(reactor._stop)
103
def fakeGetHostByName(name):
104
raise IOError("ENOBUFS (this is a funny joke)")
106
self.patch(socket, 'gethostbyname', fakeGetHostByName)
109
resolver = ThreadedResolver(reactor)
110
d = resolver.getHostByName("some.name", (timeout,))
111
self.assertFailure(d, DNSLookupError)
112
d.addCallback(failedWith.append)
114
reactor._runThreadCalls()
116
self.assertEqual(len(failedWith), 1)
118
# Make sure that any timeout-related stuff gets cleaned up.
119
reactor._clock.advance(timeout + 1)
120
self.assertEqual(reactor._clock.calls, [])
123
def test_timeout(self):
125
If L{socket.gethostbyname} does not complete before the specified
126
timeout elapsed, the L{Deferred} returned by
127
L{ThreadedResolver.getHostByBame} fails with L{DNSLookupError}.
131
reactor = FakeReactor()
132
self.addCleanup(reactor._stop)
135
def fakeGetHostByName(name):
138
self.patch(socket, 'gethostbyname', fakeGetHostByName)
141
resolver = ThreadedResolver(reactor)
142
d = resolver.getHostByName("some.name", (timeout,))
143
self.assertFailure(d, DNSLookupError)
144
d.addCallback(failedWith.append)
146
reactor._clock.advance(timeout - 1)
147
self.assertEqual(failedWith, [])
148
reactor._clock.advance(1)
149
self.assertEqual(len(failedWith), 1)
151
# Eventually the socket.gethostbyname does finish - in this case, with
152
# an exception. Nobody cares, though.
153
result.put(IOError("The I/O was errorful"))
157
class DelayedCallTests(TestCase):
159
Tests for L{DelayedCall}.
163
The string representation of a L{DelayedCall} instance, as returned by
164
C{str}, includes the unsigned id of the instance, as well as its state,
165
the function to be called, and the function arguments.
169
dc = DelayedCall(12, nothing, (3, ), {"A": 5}, None, None, lambda: 1.5)
174
except (TypeError, KeyError):
176
self.addCleanup(setIDFunction, setIDFunction(fakeID))
179
"<DelayedCall 0xc8 [10.5s] called=0 cancelled=0 nothing(3, A=5)>")