17db96d56Sopenharmony_ci# Copyright (c) 2001-2006 Twisted Matrix Laboratories. 27db96d56Sopenharmony_ci# 37db96d56Sopenharmony_ci# Permission is hereby granted, free of charge, to any person obtaining 47db96d56Sopenharmony_ci# a copy of this software and associated documentation files (the 57db96d56Sopenharmony_ci# "Software"), to deal in the Software without restriction, including 67db96d56Sopenharmony_ci# without limitation the rights to use, copy, modify, merge, publish, 77db96d56Sopenharmony_ci# distribute, sublicense, and/or sell copies of the Software, and to 87db96d56Sopenharmony_ci# permit persons to whom the Software is furnished to do so, subject to 97db96d56Sopenharmony_ci# the following conditions: 107db96d56Sopenharmony_ci# 117db96d56Sopenharmony_ci# The above copyright notice and this permission notice shall be 127db96d56Sopenharmony_ci# included in all copies or substantial portions of the Software. 137db96d56Sopenharmony_ci# 147db96d56Sopenharmony_ci# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 157db96d56Sopenharmony_ci# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 167db96d56Sopenharmony_ci# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 177db96d56Sopenharmony_ci# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 187db96d56Sopenharmony_ci# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 197db96d56Sopenharmony_ci# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 207db96d56Sopenharmony_ci# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 217db96d56Sopenharmony_ci""" 227db96d56Sopenharmony_ciTests for epoll wrapper. 237db96d56Sopenharmony_ci""" 247db96d56Sopenharmony_ciimport errno 257db96d56Sopenharmony_ciimport os 267db96d56Sopenharmony_ciimport select 277db96d56Sopenharmony_ciimport socket 287db96d56Sopenharmony_ciimport time 297db96d56Sopenharmony_ciimport unittest 307db96d56Sopenharmony_ci 317db96d56Sopenharmony_ciif not hasattr(select, "epoll"): 327db96d56Sopenharmony_ci raise unittest.SkipTest("test works only on Linux 2.6") 337db96d56Sopenharmony_ci 347db96d56Sopenharmony_citry: 357db96d56Sopenharmony_ci select.epoll() 367db96d56Sopenharmony_ciexcept OSError as e: 377db96d56Sopenharmony_ci if e.errno == errno.ENOSYS: 387db96d56Sopenharmony_ci raise unittest.SkipTest("kernel doesn't support epoll()") 397db96d56Sopenharmony_ci raise 407db96d56Sopenharmony_ci 417db96d56Sopenharmony_ciclass TestEPoll(unittest.TestCase): 427db96d56Sopenharmony_ci 437db96d56Sopenharmony_ci def setUp(self): 447db96d56Sopenharmony_ci self.serverSocket = socket.create_server(('127.0.0.1', 0)) 457db96d56Sopenharmony_ci self.connections = [self.serverSocket] 467db96d56Sopenharmony_ci 477db96d56Sopenharmony_ci def tearDown(self): 487db96d56Sopenharmony_ci for skt in self.connections: 497db96d56Sopenharmony_ci skt.close() 507db96d56Sopenharmony_ci 517db96d56Sopenharmony_ci def _connected_pair(self): 527db96d56Sopenharmony_ci client = socket.socket() 537db96d56Sopenharmony_ci client.setblocking(False) 547db96d56Sopenharmony_ci try: 557db96d56Sopenharmony_ci client.connect(('127.0.0.1', self.serverSocket.getsockname()[1])) 567db96d56Sopenharmony_ci except OSError as e: 577db96d56Sopenharmony_ci self.assertEqual(e.args[0], errno.EINPROGRESS) 587db96d56Sopenharmony_ci else: 597db96d56Sopenharmony_ci raise AssertionError("Connect should have raised EINPROGRESS") 607db96d56Sopenharmony_ci server, addr = self.serverSocket.accept() 617db96d56Sopenharmony_ci 627db96d56Sopenharmony_ci self.connections.extend((client, server)) 637db96d56Sopenharmony_ci return client, server 647db96d56Sopenharmony_ci 657db96d56Sopenharmony_ci def test_create(self): 667db96d56Sopenharmony_ci try: 677db96d56Sopenharmony_ci ep = select.epoll(16) 687db96d56Sopenharmony_ci except OSError as e: 697db96d56Sopenharmony_ci raise AssertionError(str(e)) 707db96d56Sopenharmony_ci self.assertTrue(ep.fileno() > 0, ep.fileno()) 717db96d56Sopenharmony_ci self.assertTrue(not ep.closed) 727db96d56Sopenharmony_ci ep.close() 737db96d56Sopenharmony_ci self.assertTrue(ep.closed) 747db96d56Sopenharmony_ci self.assertRaises(ValueError, ep.fileno) 757db96d56Sopenharmony_ci 767db96d56Sopenharmony_ci if hasattr(select, "EPOLL_CLOEXEC"): 777db96d56Sopenharmony_ci select.epoll(-1, select.EPOLL_CLOEXEC).close() 787db96d56Sopenharmony_ci select.epoll(flags=select.EPOLL_CLOEXEC).close() 797db96d56Sopenharmony_ci select.epoll(flags=0).close() 807db96d56Sopenharmony_ci 817db96d56Sopenharmony_ci def test_badcreate(self): 827db96d56Sopenharmony_ci self.assertRaises(TypeError, select.epoll, 1, 2, 3) 837db96d56Sopenharmony_ci self.assertRaises(TypeError, select.epoll, 'foo') 847db96d56Sopenharmony_ci self.assertRaises(TypeError, select.epoll, None) 857db96d56Sopenharmony_ci self.assertRaises(TypeError, select.epoll, ()) 867db96d56Sopenharmony_ci self.assertRaises(TypeError, select.epoll, ['foo']) 877db96d56Sopenharmony_ci self.assertRaises(TypeError, select.epoll, {}) 887db96d56Sopenharmony_ci 897db96d56Sopenharmony_ci self.assertRaises(ValueError, select.epoll, 0) 907db96d56Sopenharmony_ci self.assertRaises(ValueError, select.epoll, -2) 917db96d56Sopenharmony_ci self.assertRaises(ValueError, select.epoll, sizehint=-2) 927db96d56Sopenharmony_ci 937db96d56Sopenharmony_ci if hasattr(select, "EPOLL_CLOEXEC"): 947db96d56Sopenharmony_ci self.assertRaises(OSError, select.epoll, flags=12356) 957db96d56Sopenharmony_ci 967db96d56Sopenharmony_ci def test_context_manager(self): 977db96d56Sopenharmony_ci with select.epoll(16) as ep: 987db96d56Sopenharmony_ci self.assertGreater(ep.fileno(), 0) 997db96d56Sopenharmony_ci self.assertFalse(ep.closed) 1007db96d56Sopenharmony_ci self.assertTrue(ep.closed) 1017db96d56Sopenharmony_ci self.assertRaises(ValueError, ep.fileno) 1027db96d56Sopenharmony_ci 1037db96d56Sopenharmony_ci def test_add(self): 1047db96d56Sopenharmony_ci server, client = self._connected_pair() 1057db96d56Sopenharmony_ci 1067db96d56Sopenharmony_ci ep = select.epoll(2) 1077db96d56Sopenharmony_ci try: 1087db96d56Sopenharmony_ci ep.register(server.fileno(), select.EPOLLIN | select.EPOLLOUT) 1097db96d56Sopenharmony_ci ep.register(client.fileno(), select.EPOLLIN | select.EPOLLOUT) 1107db96d56Sopenharmony_ci finally: 1117db96d56Sopenharmony_ci ep.close() 1127db96d56Sopenharmony_ci 1137db96d56Sopenharmony_ci # adding by object w/ fileno works, too. 1147db96d56Sopenharmony_ci ep = select.epoll(2) 1157db96d56Sopenharmony_ci try: 1167db96d56Sopenharmony_ci ep.register(server, select.EPOLLIN | select.EPOLLOUT) 1177db96d56Sopenharmony_ci ep.register(client, select.EPOLLIN | select.EPOLLOUT) 1187db96d56Sopenharmony_ci finally: 1197db96d56Sopenharmony_ci ep.close() 1207db96d56Sopenharmony_ci 1217db96d56Sopenharmony_ci ep = select.epoll(2) 1227db96d56Sopenharmony_ci try: 1237db96d56Sopenharmony_ci # TypeError: argument must be an int, or have a fileno() method. 1247db96d56Sopenharmony_ci self.assertRaises(TypeError, ep.register, object(), 1257db96d56Sopenharmony_ci select.EPOLLIN | select.EPOLLOUT) 1267db96d56Sopenharmony_ci self.assertRaises(TypeError, ep.register, None, 1277db96d56Sopenharmony_ci select.EPOLLIN | select.EPOLLOUT) 1287db96d56Sopenharmony_ci # ValueError: file descriptor cannot be a negative integer (-1) 1297db96d56Sopenharmony_ci self.assertRaises(ValueError, ep.register, -1, 1307db96d56Sopenharmony_ci select.EPOLLIN | select.EPOLLOUT) 1317db96d56Sopenharmony_ci # OSError: [Errno 9] Bad file descriptor 1327db96d56Sopenharmony_ci self.assertRaises(OSError, ep.register, 10000, 1337db96d56Sopenharmony_ci select.EPOLLIN | select.EPOLLOUT) 1347db96d56Sopenharmony_ci # registering twice also raises an exception 1357db96d56Sopenharmony_ci ep.register(server, select.EPOLLIN | select.EPOLLOUT) 1367db96d56Sopenharmony_ci self.assertRaises(OSError, ep.register, server, 1377db96d56Sopenharmony_ci select.EPOLLIN | select.EPOLLOUT) 1387db96d56Sopenharmony_ci finally: 1397db96d56Sopenharmony_ci ep.close() 1407db96d56Sopenharmony_ci 1417db96d56Sopenharmony_ci def test_fromfd(self): 1427db96d56Sopenharmony_ci server, client = self._connected_pair() 1437db96d56Sopenharmony_ci 1447db96d56Sopenharmony_ci with select.epoll(2) as ep: 1457db96d56Sopenharmony_ci ep2 = select.epoll.fromfd(ep.fileno()) 1467db96d56Sopenharmony_ci 1477db96d56Sopenharmony_ci ep2.register(server.fileno(), select.EPOLLIN | select.EPOLLOUT) 1487db96d56Sopenharmony_ci ep2.register(client.fileno(), select.EPOLLIN | select.EPOLLOUT) 1497db96d56Sopenharmony_ci 1507db96d56Sopenharmony_ci events = ep.poll(1, 4) 1517db96d56Sopenharmony_ci events2 = ep2.poll(0.9, 4) 1527db96d56Sopenharmony_ci self.assertEqual(len(events), 2) 1537db96d56Sopenharmony_ci self.assertEqual(len(events2), 2) 1547db96d56Sopenharmony_ci 1557db96d56Sopenharmony_ci try: 1567db96d56Sopenharmony_ci ep2.poll(1, 4) 1577db96d56Sopenharmony_ci except OSError as e: 1587db96d56Sopenharmony_ci self.assertEqual(e.args[0], errno.EBADF, e) 1597db96d56Sopenharmony_ci else: 1607db96d56Sopenharmony_ci self.fail("epoll on closed fd didn't raise EBADF") 1617db96d56Sopenharmony_ci 1627db96d56Sopenharmony_ci def test_control_and_wait(self): 1637db96d56Sopenharmony_ci # create the epoll object 1647db96d56Sopenharmony_ci client, server = self._connected_pair() 1657db96d56Sopenharmony_ci ep = select.epoll(16) 1667db96d56Sopenharmony_ci ep.register(server.fileno(), 1677db96d56Sopenharmony_ci select.EPOLLIN | select.EPOLLOUT | select.EPOLLET) 1687db96d56Sopenharmony_ci ep.register(client.fileno(), 1697db96d56Sopenharmony_ci select.EPOLLIN | select.EPOLLOUT | select.EPOLLET) 1707db96d56Sopenharmony_ci 1717db96d56Sopenharmony_ci # EPOLLOUT 1727db96d56Sopenharmony_ci now = time.monotonic() 1737db96d56Sopenharmony_ci events = ep.poll(1, 4) 1747db96d56Sopenharmony_ci then = time.monotonic() 1757db96d56Sopenharmony_ci self.assertFalse(then - now > 0.1, then - now) 1767db96d56Sopenharmony_ci 1777db96d56Sopenharmony_ci expected = [(client.fileno(), select.EPOLLOUT), 1787db96d56Sopenharmony_ci (server.fileno(), select.EPOLLOUT)] 1797db96d56Sopenharmony_ci self.assertEqual(sorted(events), sorted(expected)) 1807db96d56Sopenharmony_ci 1817db96d56Sopenharmony_ci # no event 1827db96d56Sopenharmony_ci events = ep.poll(timeout=0.1, maxevents=4) 1837db96d56Sopenharmony_ci self.assertFalse(events) 1847db96d56Sopenharmony_ci 1857db96d56Sopenharmony_ci # send: EPOLLIN and EPOLLOUT 1867db96d56Sopenharmony_ci client.sendall(b"Hello!") 1877db96d56Sopenharmony_ci server.sendall(b"world!!!") 1887db96d56Sopenharmony_ci 1897db96d56Sopenharmony_ci now = time.monotonic() 1907db96d56Sopenharmony_ci events = ep.poll(1.0, 4) 1917db96d56Sopenharmony_ci then = time.monotonic() 1927db96d56Sopenharmony_ci self.assertFalse(then - now > 0.01) 1937db96d56Sopenharmony_ci 1947db96d56Sopenharmony_ci expected = [(client.fileno(), select.EPOLLIN | select.EPOLLOUT), 1957db96d56Sopenharmony_ci (server.fileno(), select.EPOLLIN | select.EPOLLOUT)] 1967db96d56Sopenharmony_ci self.assertEqual(sorted(events), sorted(expected)) 1977db96d56Sopenharmony_ci 1987db96d56Sopenharmony_ci # unregister, modify 1997db96d56Sopenharmony_ci ep.unregister(client.fileno()) 2007db96d56Sopenharmony_ci ep.modify(server.fileno(), select.EPOLLOUT) 2017db96d56Sopenharmony_ci now = time.monotonic() 2027db96d56Sopenharmony_ci events = ep.poll(1, 4) 2037db96d56Sopenharmony_ci then = time.monotonic() 2047db96d56Sopenharmony_ci self.assertFalse(then - now > 0.01) 2057db96d56Sopenharmony_ci 2067db96d56Sopenharmony_ci expected = [(server.fileno(), select.EPOLLOUT)] 2077db96d56Sopenharmony_ci self.assertEqual(events, expected) 2087db96d56Sopenharmony_ci 2097db96d56Sopenharmony_ci def test_errors(self): 2107db96d56Sopenharmony_ci self.assertRaises(ValueError, select.epoll, -2) 2117db96d56Sopenharmony_ci self.assertRaises(ValueError, select.epoll().register, -1, 2127db96d56Sopenharmony_ci select.EPOLLIN) 2137db96d56Sopenharmony_ci 2147db96d56Sopenharmony_ci def test_unregister_closed(self): 2157db96d56Sopenharmony_ci server, client = self._connected_pair() 2167db96d56Sopenharmony_ci fd = server.fileno() 2177db96d56Sopenharmony_ci ep = select.epoll(16) 2187db96d56Sopenharmony_ci ep.register(server) 2197db96d56Sopenharmony_ci 2207db96d56Sopenharmony_ci now = time.monotonic() 2217db96d56Sopenharmony_ci events = ep.poll(1, 4) 2227db96d56Sopenharmony_ci then = time.monotonic() 2237db96d56Sopenharmony_ci self.assertFalse(then - now > 0.01) 2247db96d56Sopenharmony_ci 2257db96d56Sopenharmony_ci server.close() 2267db96d56Sopenharmony_ci 2277db96d56Sopenharmony_ci with self.assertRaises(OSError) as cm: 2287db96d56Sopenharmony_ci ep.unregister(fd) 2297db96d56Sopenharmony_ci self.assertEqual(cm.exception.errno, errno.EBADF) 2307db96d56Sopenharmony_ci 2317db96d56Sopenharmony_ci def test_close(self): 2327db96d56Sopenharmony_ci open_file = open(__file__, "rb") 2337db96d56Sopenharmony_ci self.addCleanup(open_file.close) 2347db96d56Sopenharmony_ci fd = open_file.fileno() 2357db96d56Sopenharmony_ci epoll = select.epoll() 2367db96d56Sopenharmony_ci 2377db96d56Sopenharmony_ci # test fileno() method and closed attribute 2387db96d56Sopenharmony_ci self.assertIsInstance(epoll.fileno(), int) 2397db96d56Sopenharmony_ci self.assertFalse(epoll.closed) 2407db96d56Sopenharmony_ci 2417db96d56Sopenharmony_ci # test close() 2427db96d56Sopenharmony_ci epoll.close() 2437db96d56Sopenharmony_ci self.assertTrue(epoll.closed) 2447db96d56Sopenharmony_ci self.assertRaises(ValueError, epoll.fileno) 2457db96d56Sopenharmony_ci 2467db96d56Sopenharmony_ci # close() can be called more than once 2477db96d56Sopenharmony_ci epoll.close() 2487db96d56Sopenharmony_ci 2497db96d56Sopenharmony_ci # operations must fail with ValueError("I/O operation on closed ...") 2507db96d56Sopenharmony_ci self.assertRaises(ValueError, epoll.modify, fd, select.EPOLLIN) 2517db96d56Sopenharmony_ci self.assertRaises(ValueError, epoll.poll, 1.0) 2527db96d56Sopenharmony_ci self.assertRaises(ValueError, epoll.register, fd, select.EPOLLIN) 2537db96d56Sopenharmony_ci self.assertRaises(ValueError, epoll.unregister, fd) 2547db96d56Sopenharmony_ci 2557db96d56Sopenharmony_ci def test_fd_non_inheritable(self): 2567db96d56Sopenharmony_ci epoll = select.epoll() 2577db96d56Sopenharmony_ci self.addCleanup(epoll.close) 2587db96d56Sopenharmony_ci self.assertEqual(os.get_inheritable(epoll.fileno()), False) 2597db96d56Sopenharmony_ci 2607db96d56Sopenharmony_ci 2617db96d56Sopenharmony_ciif __name__ == "__main__": 2627db96d56Sopenharmony_ci unittest.main() 263