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