test_epoll.py revision 4adfde8bc82dd39f59e0445588c3e599ada477d
14adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# Copyright (c) 2001-2006 Twisted Matrix Laboratories. 24adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# 34adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# Permission is hereby granted, free of charge, to any person obtaining 44adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# a copy of this software and associated documentation files (the 54adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# "Software"), to deal in the Software without restriction, including 64adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# without limitation the rights to use, copy, modify, merge, publish, 74adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# distribute, sublicense, and/or sell copies of the Software, and to 84adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# permit persons to whom the Software is furnished to do so, subject to 94adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# the following conditions: 104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# 114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# The above copyright notice and this permission notice shall be 124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# included in all copies or substantial portions of the Software. 134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# 144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao""" 224adfde8bc82dd39f59e0445588c3e599ada477dJosh GaoTests for epoll wrapper. 234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao""" 244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoimport socket 254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoimport errno 264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoimport time 274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoimport select 284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoimport unittest 294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaofrom test import test_support 314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoif not hasattr(select, "epoll"): 324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao raise unittest.SkipTest("test works only on Linux 2.6") 334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaotry: 354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao select.epoll() 364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoexcept IOError, e: 374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if e.errno == errno.ENOSYS: 384adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao raise unittest.SkipTest("kernel doesn't support epoll()") 394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao raise 404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass TestEPoll(unittest.TestCase): 424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def setUp(self): 444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.serverSocket = socket.socket() 454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.serverSocket.bind(('127.0.0.1', 0)) 464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.serverSocket.listen(1) 474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.connections = [self.serverSocket] 484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def tearDown(self): 514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao for skt in self.connections: 524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao skt.close() 534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def _connected_pair(self): 554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao client = socket.socket() 564adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao client.setblocking(False) 574adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao try: 584adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao client.connect(('127.0.0.1', self.serverSocket.getsockname()[1])) 594adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao except socket.error, e: 604adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertEqual(e.args[0], errno.EINPROGRESS) 614adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao else: 624adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao raise AssertionError("Connect should have raised EINPROGRESS") 634adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao server, addr = self.serverSocket.accept() 644adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 654adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.connections.extend((client, server)) 664adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return client, server 674adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 684adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def test_create(self): 694adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao try: 704adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ep = select.epoll(16) 714adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao except OSError, e: 724adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao raise AssertionError(str(e)) 734adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertTrue(ep.fileno() > 0, ep.fileno()) 744adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertTrue(not ep.closed) 754adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ep.close() 764adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertTrue(ep.closed) 774adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertRaises(ValueError, ep.fileno) 784adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 794adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def test_badcreate(self): 804adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertRaises(TypeError, select.epoll, 1, 2, 3) 814adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertRaises(TypeError, select.epoll, 'foo') 824adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertRaises(TypeError, select.epoll, None) 834adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertRaises(TypeError, select.epoll, ()) 844adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertRaises(TypeError, select.epoll, ['foo']) 854adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertRaises(TypeError, select.epoll, {}) 864adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 874adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def test_add(self): 884adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao server, client = self._connected_pair() 894adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 904adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ep = select.epoll(2) 914adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao try: 924adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ep.register(server.fileno(), select.EPOLLIN | select.EPOLLOUT) 934adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ep.register(client.fileno(), select.EPOLLIN | select.EPOLLOUT) 944adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao finally: 954adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ep.close() 964adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 974adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # adding by object w/ fileno works, too. 984adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ep = select.epoll(2) 994adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao try: 1004adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ep.register(server, select.EPOLLIN | select.EPOLLOUT) 1014adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ep.register(client, select.EPOLLIN | select.EPOLLOUT) 1024adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao finally: 1034adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ep.close() 1044adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1054adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ep = select.epoll(2) 1064adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao try: 1074adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # TypeError: argument must be an int, or have a fileno() method. 1084adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertRaises(TypeError, ep.register, object(), 1094adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao select.EPOLLIN | select.EPOLLOUT) 1104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertRaises(TypeError, ep.register, None, 1114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao select.EPOLLIN | select.EPOLLOUT) 1124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # ValueError: file descriptor cannot be a negative integer (-1) 1134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertRaises(ValueError, ep.register, -1, 1144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao select.EPOLLIN | select.EPOLLOUT) 1154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # IOError: [Errno 9] Bad file descriptor 1164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertRaises(IOError, ep.register, 10000, 1174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao select.EPOLLIN | select.EPOLLOUT) 1184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # registering twice also raises an exception 1194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ep.register(server, select.EPOLLIN | select.EPOLLOUT) 1204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertRaises(IOError, ep.register, server, 1214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao select.EPOLLIN | select.EPOLLOUT) 1224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao finally: 1234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ep.close() 1244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def test_fromfd(self): 1264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao server, client = self._connected_pair() 1274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ep = select.epoll(2) 1294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ep2 = select.epoll.fromfd(ep.fileno()) 1304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ep2.register(server.fileno(), select.EPOLLIN | select.EPOLLOUT) 1324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ep2.register(client.fileno(), select.EPOLLIN | select.EPOLLOUT) 1334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao events = ep.poll(1, 4) 1354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao events2 = ep2.poll(0.9, 4) 1364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertEqual(len(events), 2) 1374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertEqual(len(events2), 2) 1384adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ep.close() 1404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao try: 1414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ep2.poll(1, 4) 1424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao except IOError, e: 1434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertEqual(e.args[0], errno.EBADF, e) 1444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao else: 1454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.fail("epoll on closed fd didn't raise EBADF") 1464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def test_control_and_wait(self): 1484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao client, server = self._connected_pair() 1494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ep = select.epoll(16) 1514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ep.register(server.fileno(), 1524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao select.EPOLLIN | select.EPOLLOUT | select.EPOLLET) 1534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ep.register(client.fileno(), 1544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao select.EPOLLIN | select.EPOLLOUT | select.EPOLLET) 1554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1564adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao now = time.time() 1574adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao events = ep.poll(1, 4) 1584adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao then = time.time() 1594adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertFalse(then - now > 0.1, then - now) 1604adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1614adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao events.sort() 1624adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao expected = [(client.fileno(), select.EPOLLOUT), 1634adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao (server.fileno(), select.EPOLLOUT)] 1644adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao expected.sort() 1654adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1664adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertEqual(events, expected) 1674adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertFalse(then - now > 0.01, then - now) 1684adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1694adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao now = time.time() 1704adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao events = ep.poll(timeout=2.1, maxevents=4) 1714adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao then = time.time() 1724adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertFalse(events) 1734adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1744adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao client.send("Hello!") 1754adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao server.send("world!!!") 1764adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1774adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao now = time.time() 1784adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao events = ep.poll(1, 4) 1794adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao then = time.time() 1804adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertFalse(then - now > 0.01) 1814adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1824adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao events.sort() 1834adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao expected = [(client.fileno(), select.EPOLLIN | select.EPOLLOUT), 1844adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao (server.fileno(), select.EPOLLIN | select.EPOLLOUT)] 1854adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao expected.sort() 1864adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1874adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertEqual(events, expected) 1884adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1894adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ep.unregister(client.fileno()) 1904adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ep.modify(server.fileno(), select.EPOLLOUT) 1914adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao now = time.time() 1924adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao events = ep.poll(1, 4) 1934adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao then = time.time() 1944adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertFalse(then - now > 0.01) 1954adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1964adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao expected = [(server.fileno(), select.EPOLLOUT)] 1974adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertEqual(events, expected) 1984adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1994adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def test_errors(self): 2004adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertRaises(ValueError, select.epoll, -2) 2014adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertRaises(ValueError, select.epoll().register, -1, 2024adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao select.EPOLLIN) 2034adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2044adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def test_unregister_closed(self): 2054adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao server, client = self._connected_pair() 2064adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao fd = server.fileno() 2074adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ep = select.epoll(16) 2084adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ep.register(server) 2094adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao now = time.time() 2114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao events = ep.poll(1, 4) 2124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao then = time.time() 2134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertFalse(then - now > 0.01) 2144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao server.close() 2164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ep.unregister(fd) 2174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef test_main(): 2194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao test_support.run_unittest(TestEPoll) 2204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoif __name__ == "__main__": 2224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao test_main() 223