class ReactorReaderWriterTest(unittest.TestCase): def _set_nonblocking(self, fd): flags = fcntl.fcntl(fd, fcntl.F_GETFL) fcntl.fcntl(fd, fcntl.F_SETFL, flags | os.O_NONBLOCK) def setUp(self): self._reactor = TornadoReactor(IOLoop()) r, w = os.pipe() self._set_nonblocking(r) self._set_nonblocking(w) set_close_exec(r) set_close_exec(w) self._p1 = os.fdopen(r, "rb", 0) self._p2 = os.fdopen(w, "wb", 0) def _testReadWrite(self): """ In this test the writer writes an 'x' to its fd. The reader reads it, check the value and ends the test. """ self.shouldWrite = True def checkReadInput(fd): self.assertEquals(fd.read(), 'x') self._reactor.stop() def writeOnce(fd): if self.shouldWrite: self.shouldWrite = False fd.write('x') self._reader = Reader(self._p1, checkReadInput) self._writer = Writer(self._p2, writeOnce) self._reactor.addWriter(self._writer) # Test that adding the reader twice adds it only once to # IOLoop. self._reactor.addReader(self._reader) self._reactor.addReader(self._reader) def testReadWrite(self): self._reactor.callWhenRunning(self._testReadWrite) self._reactor.run() def _testNoWriter(self): """ In this test we have no writer. Make sure the reader doesn't read anything. """ def checkReadInput(fd): self.fail("Must not be called.") def stopTest(): # Close the writer here since the IOLoop doesn't know # about it. self._writer.close() self._reactor.stop() self._reader = Reader(self._p1, checkReadInput) # We create a writer, but it should never be invoked. self._writer = Writer(self._p2, lambda fd: fd.write('x')) # Test that adding and removing the writer leaves us with no writer. self._reactor.addWriter(self._writer) self._reactor.removeWriter(self._writer) # Test that adding and removing the reader doesn't cause # unintended effects. self._reactor.addReader(self._reader) # Wake up after a moment and stop the test self._reactor.callLater(0.001, stopTest) def testNoWriter(self): self._reactor.callWhenRunning(self._testNoWriter) self._reactor.run()