1
# Copyright (c) 2009 Twisted Matrix Laboratories.
2
# See LICENSE for details.
5
Tests for implementations of L{IReactorFDSet}.
12
from twisted.internet.interfaces import IReactorFDSet
13
from twisted.internet.abstract import FileDescriptor
14
from twisted.internet.test.reactormixins import ReactorBuilder
16
# twisted.internet.tcp nicely defines some names with proper values on
17
# several different platforms.
18
from twisted.internet.tcp import EINPROGRESS, EWOULDBLOCK
21
class ReactorFDSetTestsBuilder(ReactorBuilder):
23
Builder defining tests relating to L{IReactorFDSet}.
25
requiredInterface = IReactorFDSet
27
def _connectedPair(self):
29
Return the two sockets which make up a new TCP connection.
31
serverSocket = socket.socket()
32
serverSocket.bind(('127.0.0.1', 0))
33
serverSocket.listen(1)
34
self.addCleanup(serverSocket.close)
36
client = socket.socket()
37
self.addCleanup(client.close)
38
client.setblocking(False)
40
client.connect(('127.0.0.1', serverSocket.getsockname()[1]))
41
except socket.error, e:
42
self.assertIn(e.args[0], (EINPROGRESS, EWOULDBLOCK))
44
self.fail("Connect should have raised EINPROGRESS or EWOULDBLOCK")
45
server, addr = serverSocket.accept()
46
self.addCleanup(server.close)
51
def _simpleSetup(self):
52
reactor = self.buildReactor()
54
client, server = self._connectedPair()
56
fd = FileDescriptor(reactor)
57
fd.fileno = client.fileno
59
return reactor, fd, server
62
def test_addReader(self):
64
C{reactor.addReader()} accepts an L{IReadDescriptor} provider and calls
65
its C{doRead} method when there may be data available on its C{fileno}.
67
reactor, fd, server = self._simpleSetup()
69
fd.doRead = reactor.stop
73
# The reactor will only stop if it calls fd.doRead.
74
self.runReactor(reactor)
75
# Nothing to assert, just be glad we got this far.
78
def test_removeReader(self):
80
L{reactor.removeReader()} accepts an L{IReadDescriptor} provider
81
previously passed to C{reactor.addReader()} and causes it to no longer
82
be monitored for input events.
84
reactor, fd, server = self._simpleSetup()
87
self.fail("doRead should not be called")
91
reactor.removeReader(fd)
94
# Give the reactor two timed event passes to notice that there's I/O
95
# (if it is incorrectly watching for I/O).
96
reactor.callLater(0, reactor.callLater, 0, reactor.stop)
98
self.runReactor(reactor)
99
# Getting here means the right thing happened probably.
102
def test_addWriter(self):
104
C{reactor.addWriter()} accepts an L{IWriteDescriptor} provider and
105
calls its C{doWrite} method when it may be possible to write to its
108
reactor, fd, server = self._simpleSetup()
110
fd.doWrite = reactor.stop
111
reactor.addWriter(fd)
113
self.runReactor(reactor)
114
# Getting here is great.
117
def _getFDTest(self, kind):
119
Helper for getReaders and getWriters tests.
121
reactor = self.buildReactor()
122
get = getattr(reactor, 'get' + kind + 's')
123
add = getattr(reactor, 'add' + kind)
124
remove = getattr(reactor, 'remove' + kind)
126
client, server = self._connectedPair()
128
self.assertNotIn(client, get())
129
self.assertNotIn(server, get())
132
self.assertIn(client, get())
133
self.assertNotIn(server, get())
136
self.assertNotIn(client, get())
137
self.assertNotIn(server, get())
140
def test_getReaders(self):
142
L{IReactorFDSet.getReaders} reflects the additions and removals made
143
with L{IReactorFDSet.addReader} and L{IReactorFDSet.removeReader}.
145
self._getFDTest('Reader')
148
def test_removeWriter(self):
150
L{reactor.removeWriter()} accepts an L{IWriteDescriptor} provider
151
previously passed to C{reactor.addWriter()} and causes it to no longer
152
be monitored for outputability.
154
reactor, fd, server = self._simpleSetup()
157
self.fail("doWrite should not be called")
160
reactor.addWriter(fd)
161
reactor.removeWriter(fd)
163
# Give the reactor two timed event passes to notice that there's I/O
164
# (if it is incorrectly watching for I/O).
165
reactor.callLater(0, reactor.callLater, 0, reactor.stop)
167
self.runReactor(reactor)
168
# Getting here means the right thing happened probably.
171
def test_getWriters(self):
173
L{IReactorFDSet.getWriters} reflects the additions and removals made
174
with L{IReactorFDSet.addWriter} and L{IReactorFDSet.removeWriter}.
176
self._getFDTest('Writer')
179
def test_removeAll(self):
181
C{reactor.removeAll()} removes all registered L{IReadDescriptor}
182
providers and all registered L{IWriteDescriptor} providers and returns
185
reactor = self.buildReactor()
187
reactor, fd, server = self._simpleSetup()
189
fd.doRead = lambda: self.fail("doRead should not be called")
190
fd.doWrite = lambda: self.fail("doWrite should not be called")
194
reactor.addReader(fd)
195
reactor.addWriter(fd)
197
removed = reactor.removeAll()
199
# Give the reactor two timed event passes to notice that there's I/O
200
# (if it is incorrectly watching for I/O).
201
reactor.callLater(0, reactor.callLater, 0, reactor.stop)
203
self.runReactor(reactor)
204
# Getting here means the right thing happened probably.
206
self.assertEqual(removed, [fd])
209
globals().update(ReactorFDSetTestsBuilder.makeTestCaseClasses())