Initial import to Tizen
[profile/ivi/python-twisted.git] / twisted / internet / test / test_base.py
1 # Copyright (c) Twisted Matrix Laboratories.
2 # See LICENSE for details.
3
4 """
5 Tests for L{twisted.internet.base}.
6 """
7
8 import socket
9 from Queue import Queue
10
11 from zope.interface import implements
12
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
20
21
22 class FakeReactor(object):
23     """
24     A fake reactor implementation which just supports enough reactor APIs for
25     L{ThreadedResolver}.
26     """
27     implements(IReactorTime, IReactorThreads)
28
29     def __init__(self):
30         self._clock = Clock()
31         self.callLater = self._clock.callLater
32
33         self._threadpool = ThreadPool()
34         self._threadpool.start()
35         self.getThreadPool = lambda: self._threadpool
36
37         self._threadCalls = Queue()
38
39
40     def callFromThread(self, f, *args, **kwargs):
41         self._threadCalls.put((f, args, kwargs))
42
43
44     def _runThreadCalls(self):
45         f, args, kwargs = self._threadCalls.get()
46         f(*args, **kwargs)
47
48
49     def _stop(self):
50         self._threadpool.stop()
51
52
53
54 class ThreadedResolverTests(TestCase):
55     """
56     Tests for L{ThreadedResolver}.
57     """
58     def test_success(self):
59         """
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__}.
63         """
64         ip = "10.0.0.17"
65         name = "foo.bar.example.com"
66         timeout = 30
67
68         reactor = FakeReactor()
69         self.addCleanup(reactor._stop)
70
71         lookedUp = []
72         resolvedTo = []
73         def fakeGetHostByName(name):
74             lookedUp.append(name)
75             return ip
76
77         self.patch(socket, 'gethostbyname', fakeGetHostByName)
78
79         resolver = ThreadedResolver(reactor)
80         d = resolver.getHostByName(name, (timeout,))
81         d.addCallback(resolvedTo.append)
82
83         reactor._runThreadCalls()
84
85         self.assertEqual(lookedUp, [name])
86         self.assertEqual(resolvedTo, [ip])
87
88         # Make sure that any timeout-related stuff gets cleaned up.
89         reactor._clock.advance(timeout + 1)
90         self.assertEqual(reactor._clock.calls, [])
91
92
93     def test_failure(self):
94         """
95         L{ThreadedResolver.getHostByName} returns a L{Deferred} which fires a
96         L{Failure} if the call to L{socket.gethostbyname} raises an exception.
97         """
98         timeout = 30
99
100         reactor = FakeReactor()
101         self.addCleanup(reactor._stop)
102
103         def fakeGetHostByName(name):
104             raise IOError("ENOBUFS (this is a funny joke)")
105
106         self.patch(socket, 'gethostbyname', fakeGetHostByName)
107
108         failedWith = []
109         resolver = ThreadedResolver(reactor)
110         d = resolver.getHostByName("some.name", (timeout,))
111         self.assertFailure(d, DNSLookupError)
112         d.addCallback(failedWith.append)
113
114         reactor._runThreadCalls()
115
116         self.assertEqual(len(failedWith), 1)
117
118         # Make sure that any timeout-related stuff gets cleaned up.
119         reactor._clock.advance(timeout + 1)
120         self.assertEqual(reactor._clock.calls, [])
121
122
123     def test_timeout(self):
124         """
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}.
128         """
129         timeout = 10
130
131         reactor = FakeReactor()
132         self.addCleanup(reactor._stop)
133
134         result = Queue()
135         def fakeGetHostByName(name):
136             raise result.get()
137
138         self.patch(socket, 'gethostbyname', fakeGetHostByName)
139
140         failedWith = []
141         resolver = ThreadedResolver(reactor)
142         d = resolver.getHostByName("some.name", (timeout,))
143         self.assertFailure(d, DNSLookupError)
144         d.addCallback(failedWith.append)
145
146         reactor._clock.advance(timeout - 1)
147         self.assertEqual(failedWith, [])
148         reactor._clock.advance(1)
149         self.assertEqual(len(failedWith), 1)
150
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"))
154
155
156
157 class DelayedCallTests(TestCase):
158     """
159     Tests for L{DelayedCall}.
160     """
161     def _getDelayedCallAt(self, time):
162         """
163         Get a L{DelayedCall} instance at a given C{time}.
164         
165         @param time: The absolute time at which the returned L{DelayedCall}
166             will be scheduled.
167         """
168         def noop(call):
169             pass
170         return DelayedCall(time, lambda: None, (), {}, noop, noop, None)
171
172
173     def setUp(self):
174         """
175         Create two L{DelayedCall} instanced scheduled to run at different
176         times.
177         """
178         self.zero = self._getDelayedCallAt(0)
179         self.one = self._getDelayedCallAt(1)
180
181
182     def test_str(self):
183         """
184         The string representation of a L{DelayedCall} instance, as returned by
185         C{str}, includes the unsigned id of the instance, as well as its state,
186         the function to be called, and the function arguments.
187         """
188         def nothing():
189             pass
190         dc = DelayedCall(12, nothing, (3, ), {"A": 5}, None, None, lambda: 1.5)
191         ids = {dc: 200}
192         def fakeID(obj):
193             try:
194                 return ids[obj]
195             except (TypeError, KeyError):
196                 return id(obj)
197         self.addCleanup(setIDFunction, setIDFunction(fakeID))
198         self.assertEqual(
199             str(dc),
200             "<DelayedCall 0xc8 [10.5s] called=0 cancelled=0 nothing(3, A=5)>")
201
202
203     def test_lt(self):
204         """
205         For two instances of L{DelayedCall} C{a} and C{b}, C{a < b} is true
206         if and only if C{a} is scheduled to run before C{b}.
207         """
208         zero, one = self.zero, self.one
209         self.assertTrue(zero < one)
210         self.assertFalse(one < zero)
211         self.assertFalse(zero < zero)
212         self.assertFalse(one < one)
213
214
215     def test_le(self):
216         """
217         For two instances of L{DelayedCall} C{a} and C{b}, C{a <= b} is true
218         if and only if C{a} is scheduled to run before C{b} or at the same
219         time as C{b}.
220         """
221         zero, one = self.zero, self.one
222         self.assertTrue(zero <= one)
223         self.assertFalse(one <= zero)
224         self.assertTrue(zero <= zero)
225         self.assertTrue(one <= one)
226
227
228     def test_gt(self):
229         """
230         For two instances of L{DelayedCall} C{a} and C{b}, C{a > b} is true
231         if and only if C{a} is scheduled to run after C{b}.
232         """
233         zero, one = self.zero, self.one
234         self.assertTrue(one > zero)
235         self.assertFalse(zero > one)
236         self.assertFalse(zero > zero)
237         self.assertFalse(one > one)
238
239
240     def test_ge(self):
241         """
242         For two instances of L{DelayedCall} C{a} and C{b}, C{a > b} is true
243         if and only if C{a} is scheduled to run after C{b} or at the same
244         time as C{b}.
245         """
246         zero, one = self.zero, self.one
247         self.assertTrue(one >= zero)
248         self.assertFalse(zero >= one)
249         self.assertTrue(zero >= zero)
250         self.assertTrue(one >= one)
251
252
253     def test_eq(self):
254         """
255         A L{DelayedCall} instance is only equal to itself.
256         """
257         # Explicitly use == here, instead of assertEqual, to be more
258         # confident __eq__ is being tested.
259         self.assertFalse(self.zero == self.one)
260         self.assertTrue(self.zero == self.zero)
261         self.assertTrue(self.one == self.one)
262
263
264     def test_ne(self):
265         """
266         A L{DelayedCall} instance is not equal to any other object.
267         """
268         # Explicitly use != here, instead of assertEqual, to be more
269         # confident __ne__ is being tested.
270         self.assertTrue(self.zero != self.one)
271         self.assertFalse(self.zero != self.zero)
272         self.assertFalse(self.one != self.one)