17db96d56Sopenharmony_ciimport errno 27db96d56Sopenharmony_ciimport os 37db96d56Sopenharmony_ciimport random 47db96d56Sopenharmony_ciimport selectors 57db96d56Sopenharmony_ciimport signal 67db96d56Sopenharmony_ciimport socket 77db96d56Sopenharmony_ciimport sys 87db96d56Sopenharmony_cifrom test import support 97db96d56Sopenharmony_cifrom test.support import os_helper 107db96d56Sopenharmony_cifrom test.support import socket_helper 117db96d56Sopenharmony_cifrom time import sleep 127db96d56Sopenharmony_ciimport unittest 137db96d56Sopenharmony_ciimport unittest.mock 147db96d56Sopenharmony_ciimport tempfile 157db96d56Sopenharmony_cifrom time import monotonic as time 167db96d56Sopenharmony_citry: 177db96d56Sopenharmony_ci import resource 187db96d56Sopenharmony_ciexcept ImportError: 197db96d56Sopenharmony_ci resource = None 207db96d56Sopenharmony_ci 217db96d56Sopenharmony_ci 227db96d56Sopenharmony_ciif support.is_emscripten or support.is_wasi: 237db96d56Sopenharmony_ci raise unittest.SkipTest("Cannot create socketpair on Emscripten/WASI.") 247db96d56Sopenharmony_ci 257db96d56Sopenharmony_ci 267db96d56Sopenharmony_ciif hasattr(socket, 'socketpair'): 277db96d56Sopenharmony_ci socketpair = socket.socketpair 287db96d56Sopenharmony_cielse: 297db96d56Sopenharmony_ci def socketpair(family=socket.AF_INET, type=socket.SOCK_STREAM, proto=0): 307db96d56Sopenharmony_ci with socket.socket(family, type, proto) as l: 317db96d56Sopenharmony_ci l.bind((socket_helper.HOST, 0)) 327db96d56Sopenharmony_ci l.listen() 337db96d56Sopenharmony_ci c = socket.socket(family, type, proto) 347db96d56Sopenharmony_ci try: 357db96d56Sopenharmony_ci c.connect(l.getsockname()) 367db96d56Sopenharmony_ci caddr = c.getsockname() 377db96d56Sopenharmony_ci while True: 387db96d56Sopenharmony_ci a, addr = l.accept() 397db96d56Sopenharmony_ci # check that we've got the correct client 407db96d56Sopenharmony_ci if addr == caddr: 417db96d56Sopenharmony_ci return c, a 427db96d56Sopenharmony_ci a.close() 437db96d56Sopenharmony_ci except OSError: 447db96d56Sopenharmony_ci c.close() 457db96d56Sopenharmony_ci raise 467db96d56Sopenharmony_ci 477db96d56Sopenharmony_ci 487db96d56Sopenharmony_cidef find_ready_matching(ready, flag): 497db96d56Sopenharmony_ci match = [] 507db96d56Sopenharmony_ci for key, events in ready: 517db96d56Sopenharmony_ci if events & flag: 527db96d56Sopenharmony_ci match.append(key.fileobj) 537db96d56Sopenharmony_ci return match 547db96d56Sopenharmony_ci 557db96d56Sopenharmony_ci 567db96d56Sopenharmony_ciclass BaseSelectorTestCase: 577db96d56Sopenharmony_ci 587db96d56Sopenharmony_ci def make_socketpair(self): 597db96d56Sopenharmony_ci rd, wr = socketpair() 607db96d56Sopenharmony_ci self.addCleanup(rd.close) 617db96d56Sopenharmony_ci self.addCleanup(wr.close) 627db96d56Sopenharmony_ci return rd, wr 637db96d56Sopenharmony_ci 647db96d56Sopenharmony_ci def test_register(self): 657db96d56Sopenharmony_ci s = self.SELECTOR() 667db96d56Sopenharmony_ci self.addCleanup(s.close) 677db96d56Sopenharmony_ci 687db96d56Sopenharmony_ci rd, wr = self.make_socketpair() 697db96d56Sopenharmony_ci 707db96d56Sopenharmony_ci key = s.register(rd, selectors.EVENT_READ, "data") 717db96d56Sopenharmony_ci self.assertIsInstance(key, selectors.SelectorKey) 727db96d56Sopenharmony_ci self.assertEqual(key.fileobj, rd) 737db96d56Sopenharmony_ci self.assertEqual(key.fd, rd.fileno()) 747db96d56Sopenharmony_ci self.assertEqual(key.events, selectors.EVENT_READ) 757db96d56Sopenharmony_ci self.assertEqual(key.data, "data") 767db96d56Sopenharmony_ci 777db96d56Sopenharmony_ci # register an unknown event 787db96d56Sopenharmony_ci self.assertRaises(ValueError, s.register, 0, 999999) 797db96d56Sopenharmony_ci 807db96d56Sopenharmony_ci # register an invalid FD 817db96d56Sopenharmony_ci self.assertRaises(ValueError, s.register, -10, selectors.EVENT_READ) 827db96d56Sopenharmony_ci 837db96d56Sopenharmony_ci # register twice 847db96d56Sopenharmony_ci self.assertRaises(KeyError, s.register, rd, selectors.EVENT_READ) 857db96d56Sopenharmony_ci 867db96d56Sopenharmony_ci # register the same FD, but with a different object 877db96d56Sopenharmony_ci self.assertRaises(KeyError, s.register, rd.fileno(), 887db96d56Sopenharmony_ci selectors.EVENT_READ) 897db96d56Sopenharmony_ci 907db96d56Sopenharmony_ci def test_unregister(self): 917db96d56Sopenharmony_ci s = self.SELECTOR() 927db96d56Sopenharmony_ci self.addCleanup(s.close) 937db96d56Sopenharmony_ci 947db96d56Sopenharmony_ci rd, wr = self.make_socketpair() 957db96d56Sopenharmony_ci 967db96d56Sopenharmony_ci s.register(rd, selectors.EVENT_READ) 977db96d56Sopenharmony_ci s.unregister(rd) 987db96d56Sopenharmony_ci 997db96d56Sopenharmony_ci # unregister an unknown file obj 1007db96d56Sopenharmony_ci self.assertRaises(KeyError, s.unregister, 999999) 1017db96d56Sopenharmony_ci 1027db96d56Sopenharmony_ci # unregister twice 1037db96d56Sopenharmony_ci self.assertRaises(KeyError, s.unregister, rd) 1047db96d56Sopenharmony_ci 1057db96d56Sopenharmony_ci def test_unregister_after_fd_close(self): 1067db96d56Sopenharmony_ci s = self.SELECTOR() 1077db96d56Sopenharmony_ci self.addCleanup(s.close) 1087db96d56Sopenharmony_ci rd, wr = self.make_socketpair() 1097db96d56Sopenharmony_ci r, w = rd.fileno(), wr.fileno() 1107db96d56Sopenharmony_ci s.register(r, selectors.EVENT_READ) 1117db96d56Sopenharmony_ci s.register(w, selectors.EVENT_WRITE) 1127db96d56Sopenharmony_ci rd.close() 1137db96d56Sopenharmony_ci wr.close() 1147db96d56Sopenharmony_ci s.unregister(r) 1157db96d56Sopenharmony_ci s.unregister(w) 1167db96d56Sopenharmony_ci 1177db96d56Sopenharmony_ci @unittest.skipUnless(os.name == 'posix', "requires posix") 1187db96d56Sopenharmony_ci def test_unregister_after_fd_close_and_reuse(self): 1197db96d56Sopenharmony_ci s = self.SELECTOR() 1207db96d56Sopenharmony_ci self.addCleanup(s.close) 1217db96d56Sopenharmony_ci rd, wr = self.make_socketpair() 1227db96d56Sopenharmony_ci r, w = rd.fileno(), wr.fileno() 1237db96d56Sopenharmony_ci s.register(r, selectors.EVENT_READ) 1247db96d56Sopenharmony_ci s.register(w, selectors.EVENT_WRITE) 1257db96d56Sopenharmony_ci rd2, wr2 = self.make_socketpair() 1267db96d56Sopenharmony_ci rd.close() 1277db96d56Sopenharmony_ci wr.close() 1287db96d56Sopenharmony_ci os.dup2(rd2.fileno(), r) 1297db96d56Sopenharmony_ci os.dup2(wr2.fileno(), w) 1307db96d56Sopenharmony_ci self.addCleanup(os.close, r) 1317db96d56Sopenharmony_ci self.addCleanup(os.close, w) 1327db96d56Sopenharmony_ci s.unregister(r) 1337db96d56Sopenharmony_ci s.unregister(w) 1347db96d56Sopenharmony_ci 1357db96d56Sopenharmony_ci def test_unregister_after_socket_close(self): 1367db96d56Sopenharmony_ci s = self.SELECTOR() 1377db96d56Sopenharmony_ci self.addCleanup(s.close) 1387db96d56Sopenharmony_ci rd, wr = self.make_socketpair() 1397db96d56Sopenharmony_ci s.register(rd, selectors.EVENT_READ) 1407db96d56Sopenharmony_ci s.register(wr, selectors.EVENT_WRITE) 1417db96d56Sopenharmony_ci rd.close() 1427db96d56Sopenharmony_ci wr.close() 1437db96d56Sopenharmony_ci s.unregister(rd) 1447db96d56Sopenharmony_ci s.unregister(wr) 1457db96d56Sopenharmony_ci 1467db96d56Sopenharmony_ci def test_modify(self): 1477db96d56Sopenharmony_ci s = self.SELECTOR() 1487db96d56Sopenharmony_ci self.addCleanup(s.close) 1497db96d56Sopenharmony_ci 1507db96d56Sopenharmony_ci rd, wr = self.make_socketpair() 1517db96d56Sopenharmony_ci 1527db96d56Sopenharmony_ci key = s.register(rd, selectors.EVENT_READ) 1537db96d56Sopenharmony_ci 1547db96d56Sopenharmony_ci # modify events 1557db96d56Sopenharmony_ci key2 = s.modify(rd, selectors.EVENT_WRITE) 1567db96d56Sopenharmony_ci self.assertNotEqual(key.events, key2.events) 1577db96d56Sopenharmony_ci self.assertEqual(key2, s.get_key(rd)) 1587db96d56Sopenharmony_ci 1597db96d56Sopenharmony_ci s.unregister(rd) 1607db96d56Sopenharmony_ci 1617db96d56Sopenharmony_ci # modify data 1627db96d56Sopenharmony_ci d1 = object() 1637db96d56Sopenharmony_ci d2 = object() 1647db96d56Sopenharmony_ci 1657db96d56Sopenharmony_ci key = s.register(rd, selectors.EVENT_READ, d1) 1667db96d56Sopenharmony_ci key2 = s.modify(rd, selectors.EVENT_READ, d2) 1677db96d56Sopenharmony_ci self.assertEqual(key.events, key2.events) 1687db96d56Sopenharmony_ci self.assertNotEqual(key.data, key2.data) 1697db96d56Sopenharmony_ci self.assertEqual(key2, s.get_key(rd)) 1707db96d56Sopenharmony_ci self.assertEqual(key2.data, d2) 1717db96d56Sopenharmony_ci 1727db96d56Sopenharmony_ci # modify unknown file obj 1737db96d56Sopenharmony_ci self.assertRaises(KeyError, s.modify, 999999, selectors.EVENT_READ) 1747db96d56Sopenharmony_ci 1757db96d56Sopenharmony_ci # modify use a shortcut 1767db96d56Sopenharmony_ci d3 = object() 1777db96d56Sopenharmony_ci s.register = unittest.mock.Mock() 1787db96d56Sopenharmony_ci s.unregister = unittest.mock.Mock() 1797db96d56Sopenharmony_ci 1807db96d56Sopenharmony_ci s.modify(rd, selectors.EVENT_READ, d3) 1817db96d56Sopenharmony_ci self.assertFalse(s.register.called) 1827db96d56Sopenharmony_ci self.assertFalse(s.unregister.called) 1837db96d56Sopenharmony_ci 1847db96d56Sopenharmony_ci def test_modify_unregister(self): 1857db96d56Sopenharmony_ci # Make sure the fd is unregister()ed in case of error on 1867db96d56Sopenharmony_ci # modify(): http://bugs.python.org/issue30014 1877db96d56Sopenharmony_ci if self.SELECTOR.__name__ == 'EpollSelector': 1887db96d56Sopenharmony_ci patch = unittest.mock.patch( 1897db96d56Sopenharmony_ci 'selectors.EpollSelector._selector_cls') 1907db96d56Sopenharmony_ci elif self.SELECTOR.__name__ == 'PollSelector': 1917db96d56Sopenharmony_ci patch = unittest.mock.patch( 1927db96d56Sopenharmony_ci 'selectors.PollSelector._selector_cls') 1937db96d56Sopenharmony_ci elif self.SELECTOR.__name__ == 'DevpollSelector': 1947db96d56Sopenharmony_ci patch = unittest.mock.patch( 1957db96d56Sopenharmony_ci 'selectors.DevpollSelector._selector_cls') 1967db96d56Sopenharmony_ci else: 1977db96d56Sopenharmony_ci raise self.skipTest("") 1987db96d56Sopenharmony_ci 1997db96d56Sopenharmony_ci with patch as m: 2007db96d56Sopenharmony_ci m.return_value.modify = unittest.mock.Mock( 2017db96d56Sopenharmony_ci side_effect=ZeroDivisionError) 2027db96d56Sopenharmony_ci s = self.SELECTOR() 2037db96d56Sopenharmony_ci self.addCleanup(s.close) 2047db96d56Sopenharmony_ci rd, wr = self.make_socketpair() 2057db96d56Sopenharmony_ci s.register(rd, selectors.EVENT_READ) 2067db96d56Sopenharmony_ci self.assertEqual(len(s._map), 1) 2077db96d56Sopenharmony_ci with self.assertRaises(ZeroDivisionError): 2087db96d56Sopenharmony_ci s.modify(rd, selectors.EVENT_WRITE) 2097db96d56Sopenharmony_ci self.assertEqual(len(s._map), 0) 2107db96d56Sopenharmony_ci 2117db96d56Sopenharmony_ci def test_close(self): 2127db96d56Sopenharmony_ci s = self.SELECTOR() 2137db96d56Sopenharmony_ci self.addCleanup(s.close) 2147db96d56Sopenharmony_ci 2157db96d56Sopenharmony_ci mapping = s.get_map() 2167db96d56Sopenharmony_ci rd, wr = self.make_socketpair() 2177db96d56Sopenharmony_ci 2187db96d56Sopenharmony_ci s.register(rd, selectors.EVENT_READ) 2197db96d56Sopenharmony_ci s.register(wr, selectors.EVENT_WRITE) 2207db96d56Sopenharmony_ci 2217db96d56Sopenharmony_ci s.close() 2227db96d56Sopenharmony_ci self.assertRaises(RuntimeError, s.get_key, rd) 2237db96d56Sopenharmony_ci self.assertRaises(RuntimeError, s.get_key, wr) 2247db96d56Sopenharmony_ci self.assertRaises(KeyError, mapping.__getitem__, rd) 2257db96d56Sopenharmony_ci self.assertRaises(KeyError, mapping.__getitem__, wr) 2267db96d56Sopenharmony_ci 2277db96d56Sopenharmony_ci def test_get_key(self): 2287db96d56Sopenharmony_ci s = self.SELECTOR() 2297db96d56Sopenharmony_ci self.addCleanup(s.close) 2307db96d56Sopenharmony_ci 2317db96d56Sopenharmony_ci rd, wr = self.make_socketpair() 2327db96d56Sopenharmony_ci 2337db96d56Sopenharmony_ci key = s.register(rd, selectors.EVENT_READ, "data") 2347db96d56Sopenharmony_ci self.assertEqual(key, s.get_key(rd)) 2357db96d56Sopenharmony_ci 2367db96d56Sopenharmony_ci # unknown file obj 2377db96d56Sopenharmony_ci self.assertRaises(KeyError, s.get_key, 999999) 2387db96d56Sopenharmony_ci 2397db96d56Sopenharmony_ci def test_get_map(self): 2407db96d56Sopenharmony_ci s = self.SELECTOR() 2417db96d56Sopenharmony_ci self.addCleanup(s.close) 2427db96d56Sopenharmony_ci 2437db96d56Sopenharmony_ci rd, wr = self.make_socketpair() 2447db96d56Sopenharmony_ci 2457db96d56Sopenharmony_ci keys = s.get_map() 2467db96d56Sopenharmony_ci self.assertFalse(keys) 2477db96d56Sopenharmony_ci self.assertEqual(len(keys), 0) 2487db96d56Sopenharmony_ci self.assertEqual(list(keys), []) 2497db96d56Sopenharmony_ci key = s.register(rd, selectors.EVENT_READ, "data") 2507db96d56Sopenharmony_ci self.assertIn(rd, keys) 2517db96d56Sopenharmony_ci self.assertEqual(key, keys[rd]) 2527db96d56Sopenharmony_ci self.assertEqual(len(keys), 1) 2537db96d56Sopenharmony_ci self.assertEqual(list(keys), [rd.fileno()]) 2547db96d56Sopenharmony_ci self.assertEqual(list(keys.values()), [key]) 2557db96d56Sopenharmony_ci 2567db96d56Sopenharmony_ci # unknown file obj 2577db96d56Sopenharmony_ci with self.assertRaises(KeyError): 2587db96d56Sopenharmony_ci keys[999999] 2597db96d56Sopenharmony_ci 2607db96d56Sopenharmony_ci # Read-only mapping 2617db96d56Sopenharmony_ci with self.assertRaises(TypeError): 2627db96d56Sopenharmony_ci del keys[rd] 2637db96d56Sopenharmony_ci 2647db96d56Sopenharmony_ci def test_select(self): 2657db96d56Sopenharmony_ci s = self.SELECTOR() 2667db96d56Sopenharmony_ci self.addCleanup(s.close) 2677db96d56Sopenharmony_ci 2687db96d56Sopenharmony_ci rd, wr = self.make_socketpair() 2697db96d56Sopenharmony_ci 2707db96d56Sopenharmony_ci s.register(rd, selectors.EVENT_READ) 2717db96d56Sopenharmony_ci wr_key = s.register(wr, selectors.EVENT_WRITE) 2727db96d56Sopenharmony_ci 2737db96d56Sopenharmony_ci result = s.select() 2747db96d56Sopenharmony_ci for key, events in result: 2757db96d56Sopenharmony_ci self.assertTrue(isinstance(key, selectors.SelectorKey)) 2767db96d56Sopenharmony_ci self.assertTrue(events) 2777db96d56Sopenharmony_ci self.assertFalse(events & ~(selectors.EVENT_READ | 2787db96d56Sopenharmony_ci selectors.EVENT_WRITE)) 2797db96d56Sopenharmony_ci 2807db96d56Sopenharmony_ci self.assertEqual([(wr_key, selectors.EVENT_WRITE)], result) 2817db96d56Sopenharmony_ci 2827db96d56Sopenharmony_ci def test_context_manager(self): 2837db96d56Sopenharmony_ci s = self.SELECTOR() 2847db96d56Sopenharmony_ci self.addCleanup(s.close) 2857db96d56Sopenharmony_ci 2867db96d56Sopenharmony_ci rd, wr = self.make_socketpair() 2877db96d56Sopenharmony_ci 2887db96d56Sopenharmony_ci with s as sel: 2897db96d56Sopenharmony_ci sel.register(rd, selectors.EVENT_READ) 2907db96d56Sopenharmony_ci sel.register(wr, selectors.EVENT_WRITE) 2917db96d56Sopenharmony_ci 2927db96d56Sopenharmony_ci self.assertRaises(RuntimeError, s.get_key, rd) 2937db96d56Sopenharmony_ci self.assertRaises(RuntimeError, s.get_key, wr) 2947db96d56Sopenharmony_ci 2957db96d56Sopenharmony_ci def test_fileno(self): 2967db96d56Sopenharmony_ci s = self.SELECTOR() 2977db96d56Sopenharmony_ci self.addCleanup(s.close) 2987db96d56Sopenharmony_ci 2997db96d56Sopenharmony_ci if hasattr(s, 'fileno'): 3007db96d56Sopenharmony_ci fd = s.fileno() 3017db96d56Sopenharmony_ci self.assertTrue(isinstance(fd, int)) 3027db96d56Sopenharmony_ci self.assertGreaterEqual(fd, 0) 3037db96d56Sopenharmony_ci 3047db96d56Sopenharmony_ci def test_selector(self): 3057db96d56Sopenharmony_ci s = self.SELECTOR() 3067db96d56Sopenharmony_ci self.addCleanup(s.close) 3077db96d56Sopenharmony_ci 3087db96d56Sopenharmony_ci NUM_SOCKETS = 12 3097db96d56Sopenharmony_ci MSG = b" This is a test." 3107db96d56Sopenharmony_ci MSG_LEN = len(MSG) 3117db96d56Sopenharmony_ci readers = [] 3127db96d56Sopenharmony_ci writers = [] 3137db96d56Sopenharmony_ci r2w = {} 3147db96d56Sopenharmony_ci w2r = {} 3157db96d56Sopenharmony_ci 3167db96d56Sopenharmony_ci for i in range(NUM_SOCKETS): 3177db96d56Sopenharmony_ci rd, wr = self.make_socketpair() 3187db96d56Sopenharmony_ci s.register(rd, selectors.EVENT_READ) 3197db96d56Sopenharmony_ci s.register(wr, selectors.EVENT_WRITE) 3207db96d56Sopenharmony_ci readers.append(rd) 3217db96d56Sopenharmony_ci writers.append(wr) 3227db96d56Sopenharmony_ci r2w[rd] = wr 3237db96d56Sopenharmony_ci w2r[wr] = rd 3247db96d56Sopenharmony_ci 3257db96d56Sopenharmony_ci bufs = [] 3267db96d56Sopenharmony_ci 3277db96d56Sopenharmony_ci while writers: 3287db96d56Sopenharmony_ci ready = s.select() 3297db96d56Sopenharmony_ci ready_writers = find_ready_matching(ready, selectors.EVENT_WRITE) 3307db96d56Sopenharmony_ci if not ready_writers: 3317db96d56Sopenharmony_ci self.fail("no sockets ready for writing") 3327db96d56Sopenharmony_ci wr = random.choice(ready_writers) 3337db96d56Sopenharmony_ci wr.send(MSG) 3347db96d56Sopenharmony_ci 3357db96d56Sopenharmony_ci for i in range(10): 3367db96d56Sopenharmony_ci ready = s.select() 3377db96d56Sopenharmony_ci ready_readers = find_ready_matching(ready, 3387db96d56Sopenharmony_ci selectors.EVENT_READ) 3397db96d56Sopenharmony_ci if ready_readers: 3407db96d56Sopenharmony_ci break 3417db96d56Sopenharmony_ci # there might be a delay between the write to the write end and 3427db96d56Sopenharmony_ci # the read end is reported ready 3437db96d56Sopenharmony_ci sleep(0.1) 3447db96d56Sopenharmony_ci else: 3457db96d56Sopenharmony_ci self.fail("no sockets ready for reading") 3467db96d56Sopenharmony_ci self.assertEqual([w2r[wr]], ready_readers) 3477db96d56Sopenharmony_ci rd = ready_readers[0] 3487db96d56Sopenharmony_ci buf = rd.recv(MSG_LEN) 3497db96d56Sopenharmony_ci self.assertEqual(len(buf), MSG_LEN) 3507db96d56Sopenharmony_ci bufs.append(buf) 3517db96d56Sopenharmony_ci s.unregister(r2w[rd]) 3527db96d56Sopenharmony_ci s.unregister(rd) 3537db96d56Sopenharmony_ci writers.remove(r2w[rd]) 3547db96d56Sopenharmony_ci 3557db96d56Sopenharmony_ci self.assertEqual(bufs, [MSG] * NUM_SOCKETS) 3567db96d56Sopenharmony_ci 3577db96d56Sopenharmony_ci @unittest.skipIf(sys.platform == 'win32', 3587db96d56Sopenharmony_ci 'select.select() cannot be used with empty fd sets') 3597db96d56Sopenharmony_ci def test_empty_select(self): 3607db96d56Sopenharmony_ci # Issue #23009: Make sure EpollSelector.select() works when no FD is 3617db96d56Sopenharmony_ci # registered. 3627db96d56Sopenharmony_ci s = self.SELECTOR() 3637db96d56Sopenharmony_ci self.addCleanup(s.close) 3647db96d56Sopenharmony_ci self.assertEqual(s.select(timeout=0), []) 3657db96d56Sopenharmony_ci 3667db96d56Sopenharmony_ci def test_timeout(self): 3677db96d56Sopenharmony_ci s = self.SELECTOR() 3687db96d56Sopenharmony_ci self.addCleanup(s.close) 3697db96d56Sopenharmony_ci 3707db96d56Sopenharmony_ci rd, wr = self.make_socketpair() 3717db96d56Sopenharmony_ci 3727db96d56Sopenharmony_ci s.register(wr, selectors.EVENT_WRITE) 3737db96d56Sopenharmony_ci t = time() 3747db96d56Sopenharmony_ci self.assertEqual(1, len(s.select(0))) 3757db96d56Sopenharmony_ci self.assertEqual(1, len(s.select(-1))) 3767db96d56Sopenharmony_ci self.assertLess(time() - t, 0.5) 3777db96d56Sopenharmony_ci 3787db96d56Sopenharmony_ci s.unregister(wr) 3797db96d56Sopenharmony_ci s.register(rd, selectors.EVENT_READ) 3807db96d56Sopenharmony_ci t = time() 3817db96d56Sopenharmony_ci self.assertFalse(s.select(0)) 3827db96d56Sopenharmony_ci self.assertFalse(s.select(-1)) 3837db96d56Sopenharmony_ci self.assertLess(time() - t, 0.5) 3847db96d56Sopenharmony_ci 3857db96d56Sopenharmony_ci t0 = time() 3867db96d56Sopenharmony_ci self.assertFalse(s.select(1)) 3877db96d56Sopenharmony_ci t1 = time() 3887db96d56Sopenharmony_ci dt = t1 - t0 3897db96d56Sopenharmony_ci # Tolerate 2.0 seconds for very slow buildbots 3907db96d56Sopenharmony_ci self.assertTrue(0.8 <= dt <= 2.0, dt) 3917db96d56Sopenharmony_ci 3927db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(signal, "alarm"), 3937db96d56Sopenharmony_ci "signal.alarm() required for this test") 3947db96d56Sopenharmony_ci def test_select_interrupt_exc(self): 3957db96d56Sopenharmony_ci s = self.SELECTOR() 3967db96d56Sopenharmony_ci self.addCleanup(s.close) 3977db96d56Sopenharmony_ci 3987db96d56Sopenharmony_ci rd, wr = self.make_socketpair() 3997db96d56Sopenharmony_ci 4007db96d56Sopenharmony_ci class InterruptSelect(Exception): 4017db96d56Sopenharmony_ci pass 4027db96d56Sopenharmony_ci 4037db96d56Sopenharmony_ci def handler(*args): 4047db96d56Sopenharmony_ci raise InterruptSelect 4057db96d56Sopenharmony_ci 4067db96d56Sopenharmony_ci orig_alrm_handler = signal.signal(signal.SIGALRM, handler) 4077db96d56Sopenharmony_ci self.addCleanup(signal.signal, signal.SIGALRM, orig_alrm_handler) 4087db96d56Sopenharmony_ci 4097db96d56Sopenharmony_ci try: 4107db96d56Sopenharmony_ci signal.alarm(1) 4117db96d56Sopenharmony_ci 4127db96d56Sopenharmony_ci s.register(rd, selectors.EVENT_READ) 4137db96d56Sopenharmony_ci t = time() 4147db96d56Sopenharmony_ci # select() is interrupted by a signal which raises an exception 4157db96d56Sopenharmony_ci with self.assertRaises(InterruptSelect): 4167db96d56Sopenharmony_ci s.select(30) 4177db96d56Sopenharmony_ci # select() was interrupted before the timeout of 30 seconds 4187db96d56Sopenharmony_ci self.assertLess(time() - t, 5.0) 4197db96d56Sopenharmony_ci finally: 4207db96d56Sopenharmony_ci signal.alarm(0) 4217db96d56Sopenharmony_ci 4227db96d56Sopenharmony_ci @unittest.skipUnless(hasattr(signal, "alarm"), 4237db96d56Sopenharmony_ci "signal.alarm() required for this test") 4247db96d56Sopenharmony_ci def test_select_interrupt_noraise(self): 4257db96d56Sopenharmony_ci s = self.SELECTOR() 4267db96d56Sopenharmony_ci self.addCleanup(s.close) 4277db96d56Sopenharmony_ci 4287db96d56Sopenharmony_ci rd, wr = self.make_socketpair() 4297db96d56Sopenharmony_ci 4307db96d56Sopenharmony_ci orig_alrm_handler = signal.signal(signal.SIGALRM, lambda *args: None) 4317db96d56Sopenharmony_ci self.addCleanup(signal.signal, signal.SIGALRM, orig_alrm_handler) 4327db96d56Sopenharmony_ci 4337db96d56Sopenharmony_ci try: 4347db96d56Sopenharmony_ci signal.alarm(1) 4357db96d56Sopenharmony_ci 4367db96d56Sopenharmony_ci s.register(rd, selectors.EVENT_READ) 4377db96d56Sopenharmony_ci t = time() 4387db96d56Sopenharmony_ci # select() is interrupted by a signal, but the signal handler doesn't 4397db96d56Sopenharmony_ci # raise an exception, so select() should by retries with a recomputed 4407db96d56Sopenharmony_ci # timeout 4417db96d56Sopenharmony_ci self.assertFalse(s.select(1.5)) 4427db96d56Sopenharmony_ci self.assertGreaterEqual(time() - t, 1.0) 4437db96d56Sopenharmony_ci finally: 4447db96d56Sopenharmony_ci signal.alarm(0) 4457db96d56Sopenharmony_ci 4467db96d56Sopenharmony_ci 4477db96d56Sopenharmony_ciclass ScalableSelectorMixIn: 4487db96d56Sopenharmony_ci 4497db96d56Sopenharmony_ci # see issue #18963 for why it's skipped on older OS X versions 4507db96d56Sopenharmony_ci @support.requires_mac_ver(10, 5) 4517db96d56Sopenharmony_ci @unittest.skipUnless(resource, "Test needs resource module") 4527db96d56Sopenharmony_ci def test_above_fd_setsize(self): 4537db96d56Sopenharmony_ci # A scalable implementation should have no problem with more than 4547db96d56Sopenharmony_ci # FD_SETSIZE file descriptors. Since we don't know the value, we just 4557db96d56Sopenharmony_ci # try to set the soft RLIMIT_NOFILE to the hard RLIMIT_NOFILE ceiling. 4567db96d56Sopenharmony_ci soft, hard = resource.getrlimit(resource.RLIMIT_NOFILE) 4577db96d56Sopenharmony_ci try: 4587db96d56Sopenharmony_ci resource.setrlimit(resource.RLIMIT_NOFILE, (hard, hard)) 4597db96d56Sopenharmony_ci self.addCleanup(resource.setrlimit, resource.RLIMIT_NOFILE, 4607db96d56Sopenharmony_ci (soft, hard)) 4617db96d56Sopenharmony_ci NUM_FDS = min(hard, 2**16) 4627db96d56Sopenharmony_ci except (OSError, ValueError): 4637db96d56Sopenharmony_ci NUM_FDS = soft 4647db96d56Sopenharmony_ci 4657db96d56Sopenharmony_ci # guard for already allocated FDs (stdin, stdout...) 4667db96d56Sopenharmony_ci NUM_FDS -= 32 4677db96d56Sopenharmony_ci 4687db96d56Sopenharmony_ci s = self.SELECTOR() 4697db96d56Sopenharmony_ci self.addCleanup(s.close) 4707db96d56Sopenharmony_ci 4717db96d56Sopenharmony_ci for i in range(NUM_FDS // 2): 4727db96d56Sopenharmony_ci try: 4737db96d56Sopenharmony_ci rd, wr = self.make_socketpair() 4747db96d56Sopenharmony_ci except OSError: 4757db96d56Sopenharmony_ci # too many FDs, skip - note that we should only catch EMFILE 4767db96d56Sopenharmony_ci # here, but apparently *BSD and Solaris can fail upon connect() 4777db96d56Sopenharmony_ci # or bind() with EADDRNOTAVAIL, so let's be safe 4787db96d56Sopenharmony_ci self.skipTest("FD limit reached") 4797db96d56Sopenharmony_ci 4807db96d56Sopenharmony_ci try: 4817db96d56Sopenharmony_ci s.register(rd, selectors.EVENT_READ) 4827db96d56Sopenharmony_ci s.register(wr, selectors.EVENT_WRITE) 4837db96d56Sopenharmony_ci except OSError as e: 4847db96d56Sopenharmony_ci if e.errno == errno.ENOSPC: 4857db96d56Sopenharmony_ci # this can be raised by epoll if we go over 4867db96d56Sopenharmony_ci # fs.epoll.max_user_watches sysctl 4877db96d56Sopenharmony_ci self.skipTest("FD limit reached") 4887db96d56Sopenharmony_ci raise 4897db96d56Sopenharmony_ci 4907db96d56Sopenharmony_ci try: 4917db96d56Sopenharmony_ci fds = s.select() 4927db96d56Sopenharmony_ci except OSError as e: 4937db96d56Sopenharmony_ci if e.errno == errno.EINVAL and sys.platform == 'darwin': 4947db96d56Sopenharmony_ci # unexplainable errors on macOS don't need to fail the test 4957db96d56Sopenharmony_ci self.skipTest("Invalid argument error calling poll()") 4967db96d56Sopenharmony_ci raise 4977db96d56Sopenharmony_ci self.assertEqual(NUM_FDS // 2, len(fds)) 4987db96d56Sopenharmony_ci 4997db96d56Sopenharmony_ci 5007db96d56Sopenharmony_ciclass DefaultSelectorTestCase(BaseSelectorTestCase, unittest.TestCase): 5017db96d56Sopenharmony_ci 5027db96d56Sopenharmony_ci SELECTOR = selectors.DefaultSelector 5037db96d56Sopenharmony_ci 5047db96d56Sopenharmony_ci 5057db96d56Sopenharmony_ciclass SelectSelectorTestCase(BaseSelectorTestCase, unittest.TestCase): 5067db96d56Sopenharmony_ci 5077db96d56Sopenharmony_ci SELECTOR = selectors.SelectSelector 5087db96d56Sopenharmony_ci 5097db96d56Sopenharmony_ci 5107db96d56Sopenharmony_ci@unittest.skipUnless(hasattr(selectors, 'PollSelector'), 5117db96d56Sopenharmony_ci "Test needs selectors.PollSelector") 5127db96d56Sopenharmony_ciclass PollSelectorTestCase(BaseSelectorTestCase, ScalableSelectorMixIn, 5137db96d56Sopenharmony_ci unittest.TestCase): 5147db96d56Sopenharmony_ci 5157db96d56Sopenharmony_ci SELECTOR = getattr(selectors, 'PollSelector', None) 5167db96d56Sopenharmony_ci 5177db96d56Sopenharmony_ci 5187db96d56Sopenharmony_ci@unittest.skipUnless(hasattr(selectors, 'EpollSelector'), 5197db96d56Sopenharmony_ci "Test needs selectors.EpollSelector") 5207db96d56Sopenharmony_ciclass EpollSelectorTestCase(BaseSelectorTestCase, ScalableSelectorMixIn, 5217db96d56Sopenharmony_ci unittest.TestCase): 5227db96d56Sopenharmony_ci 5237db96d56Sopenharmony_ci SELECTOR = getattr(selectors, 'EpollSelector', None) 5247db96d56Sopenharmony_ci 5257db96d56Sopenharmony_ci def test_register_file(self): 5267db96d56Sopenharmony_ci # epoll(7) returns EPERM when given a file to watch 5277db96d56Sopenharmony_ci s = self.SELECTOR() 5287db96d56Sopenharmony_ci with tempfile.NamedTemporaryFile() as f: 5297db96d56Sopenharmony_ci with self.assertRaises(IOError): 5307db96d56Sopenharmony_ci s.register(f, selectors.EVENT_READ) 5317db96d56Sopenharmony_ci # the SelectorKey has been removed 5327db96d56Sopenharmony_ci with self.assertRaises(KeyError): 5337db96d56Sopenharmony_ci s.get_key(f) 5347db96d56Sopenharmony_ci 5357db96d56Sopenharmony_ci 5367db96d56Sopenharmony_ci@unittest.skipUnless(hasattr(selectors, 'KqueueSelector'), 5377db96d56Sopenharmony_ci "Test needs selectors.KqueueSelector)") 5387db96d56Sopenharmony_ciclass KqueueSelectorTestCase(BaseSelectorTestCase, ScalableSelectorMixIn, 5397db96d56Sopenharmony_ci unittest.TestCase): 5407db96d56Sopenharmony_ci 5417db96d56Sopenharmony_ci SELECTOR = getattr(selectors, 'KqueueSelector', None) 5427db96d56Sopenharmony_ci 5437db96d56Sopenharmony_ci def test_register_bad_fd(self): 5447db96d56Sopenharmony_ci # a file descriptor that's been closed should raise an OSError 5457db96d56Sopenharmony_ci # with EBADF 5467db96d56Sopenharmony_ci s = self.SELECTOR() 5477db96d56Sopenharmony_ci bad_f = os_helper.make_bad_fd() 5487db96d56Sopenharmony_ci with self.assertRaises(OSError) as cm: 5497db96d56Sopenharmony_ci s.register(bad_f, selectors.EVENT_READ) 5507db96d56Sopenharmony_ci self.assertEqual(cm.exception.errno, errno.EBADF) 5517db96d56Sopenharmony_ci # the SelectorKey has been removed 5527db96d56Sopenharmony_ci with self.assertRaises(KeyError): 5537db96d56Sopenharmony_ci s.get_key(bad_f) 5547db96d56Sopenharmony_ci 5557db96d56Sopenharmony_ci def test_empty_select_timeout(self): 5567db96d56Sopenharmony_ci # Issues #23009, #29255: Make sure timeout is applied when no fds 5577db96d56Sopenharmony_ci # are registered. 5587db96d56Sopenharmony_ci s = self.SELECTOR() 5597db96d56Sopenharmony_ci self.addCleanup(s.close) 5607db96d56Sopenharmony_ci 5617db96d56Sopenharmony_ci t0 = time() 5627db96d56Sopenharmony_ci self.assertEqual(s.select(1), []) 5637db96d56Sopenharmony_ci t1 = time() 5647db96d56Sopenharmony_ci dt = t1 - t0 5657db96d56Sopenharmony_ci # Tolerate 2.0 seconds for very slow buildbots 5667db96d56Sopenharmony_ci self.assertTrue(0.8 <= dt <= 2.0, dt) 5677db96d56Sopenharmony_ci 5687db96d56Sopenharmony_ci 5697db96d56Sopenharmony_ci@unittest.skipUnless(hasattr(selectors, 'DevpollSelector'), 5707db96d56Sopenharmony_ci "Test needs selectors.DevpollSelector") 5717db96d56Sopenharmony_ciclass DevpollSelectorTestCase(BaseSelectorTestCase, ScalableSelectorMixIn, 5727db96d56Sopenharmony_ci unittest.TestCase): 5737db96d56Sopenharmony_ci 5747db96d56Sopenharmony_ci SELECTOR = getattr(selectors, 'DevpollSelector', None) 5757db96d56Sopenharmony_ci 5767db96d56Sopenharmony_ci 5777db96d56Sopenharmony_cidef tearDownModule(): 5787db96d56Sopenharmony_ci support.reap_children() 5797db96d56Sopenharmony_ci 5807db96d56Sopenharmony_ci 5817db96d56Sopenharmony_ciif __name__ == "__main__": 5827db96d56Sopenharmony_ci unittest.main() 583