1 # Copyright (c) Twisted Matrix Laboratories.
2 # See LICENSE for details.
5 Tests for L{twisted.internet.stdio}.
8 from twisted.python.runtime import platform
9 from twisted.internet.test.reactormixins import ReactorBuilder
10 from twisted.internet.protocol import Protocol
11 if not platform.isWindows():
12 from twisted.internet._posixstdio import StandardIO
16 class StdioFilesTests(ReactorBuilder):
18 L{StandardIO} supports reading and writing to filesystem files.
23 file(path, "w").close()
24 self.extraFile = file(path, "r+")
27 def test_addReader(self):
29 Adding a filesystem file reader to a reactor will make sure it is
32 reactor = self.buildReactor()
34 class DataProtocol(Protocol):
36 def dataReceived(self, data):
38 # It'd be better to stop reactor on connectionLost, but that
39 # fails on FreeBSD, probably due to
40 # http://bugs.python.org/issue9591:
41 if self.data == "hello!":
50 # Read bytes from a file, deliver them to a protocol instance:
51 protocol = DataProtocol()
52 StandardIO(protocol, stdin=f.fileno(),
53 stdout=self.extraFile.fileno(),
56 self.runReactor(reactor)
57 self.assertEqual(protocol.data, "hello!")
60 def test_addWriter(self):
62 Adding a filesystem file writer to a reactor will make sure it is
65 reactor = self.buildReactor()
67 class DisconnectProtocol(Protocol):
68 def connectionLost(self, reason):
74 # Write bytes to a transport, hopefully have them written to a file:
75 protocol = DisconnectProtocol()
76 StandardIO(protocol, stdout=f.fileno(),
77 stdin=self.extraFile.fileno(), reactor=reactor)
78 protocol.transport.write("hello")
79 protocol.transport.write(", world")
80 protocol.transport.loseConnection()
82 self.runReactor(reactor)
85 self.assertEqual(f.read(), "hello, world")
89 def test_removeReader(self):
91 Removing a filesystem file reader from a reactor will make sure it is
94 reactor = self.buildReactor()
95 self.addCleanup(self.unbuildReactor, reactor)
98 file(path, "w").close()
99 # Cleanup might fail if file is GCed too soon:
100 self.f = f = file(path, "r")
102 # Have the reader added:
103 stdio = StandardIO(Protocol(), stdin=f.fileno(),
104 stdout=self.extraFile.fileno(),
106 self.assertIn(stdio._reader, reactor.getReaders())
107 stdio._reader.stopReading()
108 self.assertNotIn(stdio._reader, reactor.getReaders())
111 def test_removeWriter(self):
113 Removing a filesystem file writer from a reactor will make sure it is
116 reactor = self.buildReactor()
117 self.addCleanup(self.unbuildReactor, reactor)
119 # Cleanup might fail if file is GCed too soon:
120 self.f = f = file(self.mktemp(), "w")
122 # Have the reader added:
123 protocol = Protocol()
124 stdio = StandardIO(protocol, stdout=f.fileno(),
125 stdin=self.extraFile.fileno(),
127 protocol.transport.write("hello")
128 self.assertIn(stdio._writer, reactor.getWriters())
129 stdio._writer.stopWriting()
130 self.assertNotIn(stdio._writer, reactor.getWriters())
133 def test_removeAll(self):
135 Calling C{removeAll} on a reactor includes descriptors that are
138 reactor = self.buildReactor()
139 self.addCleanup(self.unbuildReactor, reactor)
142 file(path, "w").close()
143 # Cleanup might fail if file is GCed too soon:
144 self.f = f = file(path, "r")
146 # Have the reader added:
147 stdio = StandardIO(Protocol(), stdin=f.fileno(),
148 stdout=self.extraFile.fileno(), reactor=reactor)
150 removed = reactor.removeAll()
151 self.assertIn(stdio._reader, removed)
152 self.assertNotIn(stdio._reader, reactor.getReaders())
155 def test_getReaders(self):
157 C{reactor.getReaders} includes descriptors that are filesystem files.
159 reactor = self.buildReactor()
160 self.addCleanup(self.unbuildReactor, reactor)
163 file(path, "w").close()
164 # Cleanup might fail if file is GCed too soon:
165 self.f = f = file(path, "r")
167 # Have the reader added:
168 stdio = StandardIO(Protocol(), stdin=f.fileno(),
169 stdout=self.extraFile.fileno(), reactor=reactor)
170 self.assertIn(stdio._reader, reactor.getReaders())
173 def test_getWriters(self):
175 C{reactor.getWriters} includes descriptors that are filesystem files.
177 reactor = self.buildReactor()
178 self.addCleanup(self.unbuildReactor, reactor)
180 # Cleanup might fail if file is GCed too soon:
181 self.f = f = file(self.mktemp(), "w")
183 # Have the reader added:
184 stdio = StandardIO(Protocol(), stdout=f.fileno(),
185 stdin=self.extraFile.fileno(), reactor=reactor)
186 self.assertNotIn(stdio._writer, reactor.getWriters())
187 stdio._writer.startWriting()
188 self.assertIn(stdio._writer, reactor.getWriters())
190 if platform.isWindows():
191 skip = ("StandardIO does not accept stdout as an argument to Windows. "
192 "Testing redirection to a file is therefore harder.")
195 globals().update(StdioFilesTests.makeTestCaseClasses())