17db96d56Sopenharmony_cifrom collections import namedtuple 27db96d56Sopenharmony_ciimport contextlib 37db96d56Sopenharmony_ciimport itertools 47db96d56Sopenharmony_ciimport os 57db96d56Sopenharmony_ciimport pickle 67db96d56Sopenharmony_ciimport sys 77db96d56Sopenharmony_cifrom textwrap import dedent 87db96d56Sopenharmony_ciimport threading 97db96d56Sopenharmony_ciimport time 107db96d56Sopenharmony_ciimport unittest 117db96d56Sopenharmony_ci 127db96d56Sopenharmony_cifrom test import support 137db96d56Sopenharmony_cifrom test.support import import_helper 147db96d56Sopenharmony_cifrom test.support import script_helper 157db96d56Sopenharmony_ci 167db96d56Sopenharmony_ci 177db96d56Sopenharmony_ciinterpreters = import_helper.import_module('_xxsubinterpreters') 187db96d56Sopenharmony_ci 197db96d56Sopenharmony_ci 207db96d56Sopenharmony_ci################################## 217db96d56Sopenharmony_ci# helpers 227db96d56Sopenharmony_ci 237db96d56Sopenharmony_cidef _captured_script(script): 247db96d56Sopenharmony_ci r, w = os.pipe() 257db96d56Sopenharmony_ci indented = script.replace('\n', '\n ') 267db96d56Sopenharmony_ci wrapped = dedent(f""" 277db96d56Sopenharmony_ci import contextlib 287db96d56Sopenharmony_ci with open({w}, 'w', encoding="utf-8") as spipe: 297db96d56Sopenharmony_ci with contextlib.redirect_stdout(spipe): 307db96d56Sopenharmony_ci {indented} 317db96d56Sopenharmony_ci """) 327db96d56Sopenharmony_ci return wrapped, open(r, encoding="utf-8") 337db96d56Sopenharmony_ci 347db96d56Sopenharmony_ci 357db96d56Sopenharmony_cidef _run_output(interp, request, shared=None): 367db96d56Sopenharmony_ci script, rpipe = _captured_script(request) 377db96d56Sopenharmony_ci with rpipe: 387db96d56Sopenharmony_ci interpreters.run_string(interp, script, shared) 397db96d56Sopenharmony_ci return rpipe.read() 407db96d56Sopenharmony_ci 417db96d56Sopenharmony_ci 427db96d56Sopenharmony_cidef _wait_for_interp_to_run(interp, timeout=None): 437db96d56Sopenharmony_ci # bpo-37224: Running this test file in multiprocesses will fail randomly. 447db96d56Sopenharmony_ci # The failure reason is that the thread can't acquire the cpu to 457db96d56Sopenharmony_ci # run subinterpreter eariler than the main thread in multiprocess. 467db96d56Sopenharmony_ci if timeout is None: 477db96d56Sopenharmony_ci timeout = support.SHORT_TIMEOUT 487db96d56Sopenharmony_ci start_time = time.monotonic() 497db96d56Sopenharmony_ci deadline = start_time + timeout 507db96d56Sopenharmony_ci while not interpreters.is_running(interp): 517db96d56Sopenharmony_ci if time.monotonic() > deadline: 527db96d56Sopenharmony_ci raise RuntimeError('interp is not running') 537db96d56Sopenharmony_ci time.sleep(0.010) 547db96d56Sopenharmony_ci 557db96d56Sopenharmony_ci 567db96d56Sopenharmony_ci@contextlib.contextmanager 577db96d56Sopenharmony_cidef _running(interp): 587db96d56Sopenharmony_ci r, w = os.pipe() 597db96d56Sopenharmony_ci def run(): 607db96d56Sopenharmony_ci interpreters.run_string(interp, dedent(f""" 617db96d56Sopenharmony_ci # wait for "signal" 627db96d56Sopenharmony_ci with open({r}, encoding="utf-8") as rpipe: 637db96d56Sopenharmony_ci rpipe.read() 647db96d56Sopenharmony_ci """)) 657db96d56Sopenharmony_ci 667db96d56Sopenharmony_ci t = threading.Thread(target=run) 677db96d56Sopenharmony_ci t.start() 687db96d56Sopenharmony_ci _wait_for_interp_to_run(interp) 697db96d56Sopenharmony_ci 707db96d56Sopenharmony_ci yield 717db96d56Sopenharmony_ci 727db96d56Sopenharmony_ci with open(w, 'w', encoding="utf-8") as spipe: 737db96d56Sopenharmony_ci spipe.write('done') 747db96d56Sopenharmony_ci t.join() 757db96d56Sopenharmony_ci 767db96d56Sopenharmony_ci 777db96d56Sopenharmony_ci#@contextmanager 787db96d56Sopenharmony_ci#def run_threaded(id, source, **shared): 797db96d56Sopenharmony_ci# def run(): 807db96d56Sopenharmony_ci# run_interp(id, source, **shared) 817db96d56Sopenharmony_ci# t = threading.Thread(target=run) 827db96d56Sopenharmony_ci# t.start() 837db96d56Sopenharmony_ci# yield 847db96d56Sopenharmony_ci# t.join() 857db96d56Sopenharmony_ci 867db96d56Sopenharmony_ci 877db96d56Sopenharmony_cidef run_interp(id, source, **shared): 887db96d56Sopenharmony_ci _run_interp(id, source, shared) 897db96d56Sopenharmony_ci 907db96d56Sopenharmony_ci 917db96d56Sopenharmony_cidef _run_interp(id, source, shared, _mainns={}): 927db96d56Sopenharmony_ci source = dedent(source) 937db96d56Sopenharmony_ci main = interpreters.get_main() 947db96d56Sopenharmony_ci if main == id: 957db96d56Sopenharmony_ci if interpreters.get_current() != main: 967db96d56Sopenharmony_ci raise RuntimeError 977db96d56Sopenharmony_ci # XXX Run a func? 987db96d56Sopenharmony_ci exec(source, _mainns) 997db96d56Sopenharmony_ci else: 1007db96d56Sopenharmony_ci interpreters.run_string(id, source, shared) 1017db96d56Sopenharmony_ci 1027db96d56Sopenharmony_ci 1037db96d56Sopenharmony_ciclass Interpreter(namedtuple('Interpreter', 'name id')): 1047db96d56Sopenharmony_ci 1057db96d56Sopenharmony_ci @classmethod 1067db96d56Sopenharmony_ci def from_raw(cls, raw): 1077db96d56Sopenharmony_ci if isinstance(raw, cls): 1087db96d56Sopenharmony_ci return raw 1097db96d56Sopenharmony_ci elif isinstance(raw, str): 1107db96d56Sopenharmony_ci return cls(raw) 1117db96d56Sopenharmony_ci else: 1127db96d56Sopenharmony_ci raise NotImplementedError 1137db96d56Sopenharmony_ci 1147db96d56Sopenharmony_ci def __new__(cls, name=None, id=None): 1157db96d56Sopenharmony_ci main = interpreters.get_main() 1167db96d56Sopenharmony_ci if id == main: 1177db96d56Sopenharmony_ci if not name: 1187db96d56Sopenharmony_ci name = 'main' 1197db96d56Sopenharmony_ci elif name != 'main': 1207db96d56Sopenharmony_ci raise ValueError( 1217db96d56Sopenharmony_ci 'name mismatch (expected "main", got "{}")'.format(name)) 1227db96d56Sopenharmony_ci id = main 1237db96d56Sopenharmony_ci elif id is not None: 1247db96d56Sopenharmony_ci if not name: 1257db96d56Sopenharmony_ci name = 'interp' 1267db96d56Sopenharmony_ci elif name == 'main': 1277db96d56Sopenharmony_ci raise ValueError('name mismatch (unexpected "main")') 1287db96d56Sopenharmony_ci if not isinstance(id, interpreters.InterpreterID): 1297db96d56Sopenharmony_ci id = interpreters.InterpreterID(id) 1307db96d56Sopenharmony_ci elif not name or name == 'main': 1317db96d56Sopenharmony_ci name = 'main' 1327db96d56Sopenharmony_ci id = main 1337db96d56Sopenharmony_ci else: 1347db96d56Sopenharmony_ci id = interpreters.create() 1357db96d56Sopenharmony_ci self = super().__new__(cls, name, id) 1367db96d56Sopenharmony_ci return self 1377db96d56Sopenharmony_ci 1387db96d56Sopenharmony_ci 1397db96d56Sopenharmony_ci# XXX expect_channel_closed() is unnecessary once we improve exc propagation. 1407db96d56Sopenharmony_ci 1417db96d56Sopenharmony_ci@contextlib.contextmanager 1427db96d56Sopenharmony_cidef expect_channel_closed(): 1437db96d56Sopenharmony_ci try: 1447db96d56Sopenharmony_ci yield 1457db96d56Sopenharmony_ci except interpreters.ChannelClosedError: 1467db96d56Sopenharmony_ci pass 1477db96d56Sopenharmony_ci else: 1487db96d56Sopenharmony_ci assert False, 'channel not closed' 1497db96d56Sopenharmony_ci 1507db96d56Sopenharmony_ci 1517db96d56Sopenharmony_ciclass ChannelAction(namedtuple('ChannelAction', 'action end interp')): 1527db96d56Sopenharmony_ci 1537db96d56Sopenharmony_ci def __new__(cls, action, end=None, interp=None): 1547db96d56Sopenharmony_ci if not end: 1557db96d56Sopenharmony_ci end = 'both' 1567db96d56Sopenharmony_ci if not interp: 1577db96d56Sopenharmony_ci interp = 'main' 1587db96d56Sopenharmony_ci self = super().__new__(cls, action, end, interp) 1597db96d56Sopenharmony_ci return self 1607db96d56Sopenharmony_ci 1617db96d56Sopenharmony_ci def __init__(self, *args, **kwargs): 1627db96d56Sopenharmony_ci if self.action == 'use': 1637db96d56Sopenharmony_ci if self.end not in ('same', 'opposite', 'send', 'recv'): 1647db96d56Sopenharmony_ci raise ValueError(self.end) 1657db96d56Sopenharmony_ci elif self.action in ('close', 'force-close'): 1667db96d56Sopenharmony_ci if self.end not in ('both', 'same', 'opposite', 'send', 'recv'): 1677db96d56Sopenharmony_ci raise ValueError(self.end) 1687db96d56Sopenharmony_ci else: 1697db96d56Sopenharmony_ci raise ValueError(self.action) 1707db96d56Sopenharmony_ci if self.interp not in ('main', 'same', 'other', 'extra'): 1717db96d56Sopenharmony_ci raise ValueError(self.interp) 1727db96d56Sopenharmony_ci 1737db96d56Sopenharmony_ci def resolve_end(self, end): 1747db96d56Sopenharmony_ci if self.end == 'same': 1757db96d56Sopenharmony_ci return end 1767db96d56Sopenharmony_ci elif self.end == 'opposite': 1777db96d56Sopenharmony_ci return 'recv' if end == 'send' else 'send' 1787db96d56Sopenharmony_ci else: 1797db96d56Sopenharmony_ci return self.end 1807db96d56Sopenharmony_ci 1817db96d56Sopenharmony_ci def resolve_interp(self, interp, other, extra): 1827db96d56Sopenharmony_ci if self.interp == 'same': 1837db96d56Sopenharmony_ci return interp 1847db96d56Sopenharmony_ci elif self.interp == 'other': 1857db96d56Sopenharmony_ci if other is None: 1867db96d56Sopenharmony_ci raise RuntimeError 1877db96d56Sopenharmony_ci return other 1887db96d56Sopenharmony_ci elif self.interp == 'extra': 1897db96d56Sopenharmony_ci if extra is None: 1907db96d56Sopenharmony_ci raise RuntimeError 1917db96d56Sopenharmony_ci return extra 1927db96d56Sopenharmony_ci elif self.interp == 'main': 1937db96d56Sopenharmony_ci if interp.name == 'main': 1947db96d56Sopenharmony_ci return interp 1957db96d56Sopenharmony_ci elif other and other.name == 'main': 1967db96d56Sopenharmony_ci return other 1977db96d56Sopenharmony_ci else: 1987db96d56Sopenharmony_ci raise RuntimeError 1997db96d56Sopenharmony_ci # Per __init__(), there aren't any others. 2007db96d56Sopenharmony_ci 2017db96d56Sopenharmony_ci 2027db96d56Sopenharmony_ciclass ChannelState(namedtuple('ChannelState', 'pending closed')): 2037db96d56Sopenharmony_ci 2047db96d56Sopenharmony_ci def __new__(cls, pending=0, *, closed=False): 2057db96d56Sopenharmony_ci self = super().__new__(cls, pending, closed) 2067db96d56Sopenharmony_ci return self 2077db96d56Sopenharmony_ci 2087db96d56Sopenharmony_ci def incr(self): 2097db96d56Sopenharmony_ci return type(self)(self.pending + 1, closed=self.closed) 2107db96d56Sopenharmony_ci 2117db96d56Sopenharmony_ci def decr(self): 2127db96d56Sopenharmony_ci return type(self)(self.pending - 1, closed=self.closed) 2137db96d56Sopenharmony_ci 2147db96d56Sopenharmony_ci def close(self, *, force=True): 2157db96d56Sopenharmony_ci if self.closed: 2167db96d56Sopenharmony_ci if not force or self.pending == 0: 2177db96d56Sopenharmony_ci return self 2187db96d56Sopenharmony_ci return type(self)(0 if force else self.pending, closed=True) 2197db96d56Sopenharmony_ci 2207db96d56Sopenharmony_ci 2217db96d56Sopenharmony_cidef run_action(cid, action, end, state, *, hideclosed=True): 2227db96d56Sopenharmony_ci if state.closed: 2237db96d56Sopenharmony_ci if action == 'use' and end == 'recv' and state.pending: 2247db96d56Sopenharmony_ci expectfail = False 2257db96d56Sopenharmony_ci else: 2267db96d56Sopenharmony_ci expectfail = True 2277db96d56Sopenharmony_ci else: 2287db96d56Sopenharmony_ci expectfail = False 2297db96d56Sopenharmony_ci 2307db96d56Sopenharmony_ci try: 2317db96d56Sopenharmony_ci result = _run_action(cid, action, end, state) 2327db96d56Sopenharmony_ci except interpreters.ChannelClosedError: 2337db96d56Sopenharmony_ci if not hideclosed and not expectfail: 2347db96d56Sopenharmony_ci raise 2357db96d56Sopenharmony_ci result = state.close() 2367db96d56Sopenharmony_ci else: 2377db96d56Sopenharmony_ci if expectfail: 2387db96d56Sopenharmony_ci raise ... # XXX 2397db96d56Sopenharmony_ci return result 2407db96d56Sopenharmony_ci 2417db96d56Sopenharmony_ci 2427db96d56Sopenharmony_cidef _run_action(cid, action, end, state): 2437db96d56Sopenharmony_ci if action == 'use': 2447db96d56Sopenharmony_ci if end == 'send': 2457db96d56Sopenharmony_ci interpreters.channel_send(cid, b'spam') 2467db96d56Sopenharmony_ci return state.incr() 2477db96d56Sopenharmony_ci elif end == 'recv': 2487db96d56Sopenharmony_ci if not state.pending: 2497db96d56Sopenharmony_ci try: 2507db96d56Sopenharmony_ci interpreters.channel_recv(cid) 2517db96d56Sopenharmony_ci except interpreters.ChannelEmptyError: 2527db96d56Sopenharmony_ci return state 2537db96d56Sopenharmony_ci else: 2547db96d56Sopenharmony_ci raise Exception('expected ChannelEmptyError') 2557db96d56Sopenharmony_ci else: 2567db96d56Sopenharmony_ci interpreters.channel_recv(cid) 2577db96d56Sopenharmony_ci return state.decr() 2587db96d56Sopenharmony_ci else: 2597db96d56Sopenharmony_ci raise ValueError(end) 2607db96d56Sopenharmony_ci elif action == 'close': 2617db96d56Sopenharmony_ci kwargs = {} 2627db96d56Sopenharmony_ci if end in ('recv', 'send'): 2637db96d56Sopenharmony_ci kwargs[end] = True 2647db96d56Sopenharmony_ci interpreters.channel_close(cid, **kwargs) 2657db96d56Sopenharmony_ci return state.close() 2667db96d56Sopenharmony_ci elif action == 'force-close': 2677db96d56Sopenharmony_ci kwargs = { 2687db96d56Sopenharmony_ci 'force': True, 2697db96d56Sopenharmony_ci } 2707db96d56Sopenharmony_ci if end in ('recv', 'send'): 2717db96d56Sopenharmony_ci kwargs[end] = True 2727db96d56Sopenharmony_ci interpreters.channel_close(cid, **kwargs) 2737db96d56Sopenharmony_ci return state.close(force=True) 2747db96d56Sopenharmony_ci else: 2757db96d56Sopenharmony_ci raise ValueError(action) 2767db96d56Sopenharmony_ci 2777db96d56Sopenharmony_ci 2787db96d56Sopenharmony_cidef clean_up_interpreters(): 2797db96d56Sopenharmony_ci for id in interpreters.list_all(): 2807db96d56Sopenharmony_ci if id == 0: # main 2817db96d56Sopenharmony_ci continue 2827db96d56Sopenharmony_ci try: 2837db96d56Sopenharmony_ci interpreters.destroy(id) 2847db96d56Sopenharmony_ci except RuntimeError: 2857db96d56Sopenharmony_ci pass # already destroyed 2867db96d56Sopenharmony_ci 2877db96d56Sopenharmony_ci 2887db96d56Sopenharmony_cidef clean_up_channels(): 2897db96d56Sopenharmony_ci for cid in interpreters.channel_list_all(): 2907db96d56Sopenharmony_ci try: 2917db96d56Sopenharmony_ci interpreters.channel_destroy(cid) 2927db96d56Sopenharmony_ci except interpreters.ChannelNotFoundError: 2937db96d56Sopenharmony_ci pass # already destroyed 2947db96d56Sopenharmony_ci 2957db96d56Sopenharmony_ci 2967db96d56Sopenharmony_ciclass TestBase(unittest.TestCase): 2977db96d56Sopenharmony_ci 2987db96d56Sopenharmony_ci def tearDown(self): 2997db96d56Sopenharmony_ci clean_up_interpreters() 3007db96d56Sopenharmony_ci clean_up_channels() 3017db96d56Sopenharmony_ci 3027db96d56Sopenharmony_ci 3037db96d56Sopenharmony_ci################################## 3047db96d56Sopenharmony_ci# misc. tests 3057db96d56Sopenharmony_ci 3067db96d56Sopenharmony_ciclass IsShareableTests(unittest.TestCase): 3077db96d56Sopenharmony_ci 3087db96d56Sopenharmony_ci def test_default_shareables(self): 3097db96d56Sopenharmony_ci shareables = [ 3107db96d56Sopenharmony_ci # singletons 3117db96d56Sopenharmony_ci None, 3127db96d56Sopenharmony_ci # builtin objects 3137db96d56Sopenharmony_ci b'spam', 3147db96d56Sopenharmony_ci 'spam', 3157db96d56Sopenharmony_ci 10, 3167db96d56Sopenharmony_ci -10, 3177db96d56Sopenharmony_ci ] 3187db96d56Sopenharmony_ci for obj in shareables: 3197db96d56Sopenharmony_ci with self.subTest(obj): 3207db96d56Sopenharmony_ci self.assertTrue( 3217db96d56Sopenharmony_ci interpreters.is_shareable(obj)) 3227db96d56Sopenharmony_ci 3237db96d56Sopenharmony_ci def test_not_shareable(self): 3247db96d56Sopenharmony_ci class Cheese: 3257db96d56Sopenharmony_ci def __init__(self, name): 3267db96d56Sopenharmony_ci self.name = name 3277db96d56Sopenharmony_ci def __str__(self): 3287db96d56Sopenharmony_ci return self.name 3297db96d56Sopenharmony_ci 3307db96d56Sopenharmony_ci class SubBytes(bytes): 3317db96d56Sopenharmony_ci """A subclass of a shareable type.""" 3327db96d56Sopenharmony_ci 3337db96d56Sopenharmony_ci not_shareables = [ 3347db96d56Sopenharmony_ci # singletons 3357db96d56Sopenharmony_ci True, 3367db96d56Sopenharmony_ci False, 3377db96d56Sopenharmony_ci NotImplemented, 3387db96d56Sopenharmony_ci ..., 3397db96d56Sopenharmony_ci # builtin types and objects 3407db96d56Sopenharmony_ci type, 3417db96d56Sopenharmony_ci object, 3427db96d56Sopenharmony_ci object(), 3437db96d56Sopenharmony_ci Exception(), 3447db96d56Sopenharmony_ci 100.0, 3457db96d56Sopenharmony_ci # user-defined types and objects 3467db96d56Sopenharmony_ci Cheese, 3477db96d56Sopenharmony_ci Cheese('Wensleydale'), 3487db96d56Sopenharmony_ci SubBytes(b'spam'), 3497db96d56Sopenharmony_ci ] 3507db96d56Sopenharmony_ci for obj in not_shareables: 3517db96d56Sopenharmony_ci with self.subTest(repr(obj)): 3527db96d56Sopenharmony_ci self.assertFalse( 3537db96d56Sopenharmony_ci interpreters.is_shareable(obj)) 3547db96d56Sopenharmony_ci 3557db96d56Sopenharmony_ci 3567db96d56Sopenharmony_ciclass ShareableTypeTests(unittest.TestCase): 3577db96d56Sopenharmony_ci 3587db96d56Sopenharmony_ci def setUp(self): 3597db96d56Sopenharmony_ci super().setUp() 3607db96d56Sopenharmony_ci self.cid = interpreters.channel_create() 3617db96d56Sopenharmony_ci 3627db96d56Sopenharmony_ci def tearDown(self): 3637db96d56Sopenharmony_ci interpreters.channel_destroy(self.cid) 3647db96d56Sopenharmony_ci super().tearDown() 3657db96d56Sopenharmony_ci 3667db96d56Sopenharmony_ci def _assert_values(self, values): 3677db96d56Sopenharmony_ci for obj in values: 3687db96d56Sopenharmony_ci with self.subTest(obj): 3697db96d56Sopenharmony_ci interpreters.channel_send(self.cid, obj) 3707db96d56Sopenharmony_ci got = interpreters.channel_recv(self.cid) 3717db96d56Sopenharmony_ci 3727db96d56Sopenharmony_ci self.assertEqual(got, obj) 3737db96d56Sopenharmony_ci self.assertIs(type(got), type(obj)) 3747db96d56Sopenharmony_ci # XXX Check the following in the channel tests? 3757db96d56Sopenharmony_ci #self.assertIsNot(got, obj) 3767db96d56Sopenharmony_ci 3777db96d56Sopenharmony_ci def test_singletons(self): 3787db96d56Sopenharmony_ci for obj in [None]: 3797db96d56Sopenharmony_ci with self.subTest(obj): 3807db96d56Sopenharmony_ci interpreters.channel_send(self.cid, obj) 3817db96d56Sopenharmony_ci got = interpreters.channel_recv(self.cid) 3827db96d56Sopenharmony_ci 3837db96d56Sopenharmony_ci # XXX What about between interpreters? 3847db96d56Sopenharmony_ci self.assertIs(got, obj) 3857db96d56Sopenharmony_ci 3867db96d56Sopenharmony_ci def test_types(self): 3877db96d56Sopenharmony_ci self._assert_values([ 3887db96d56Sopenharmony_ci b'spam', 3897db96d56Sopenharmony_ci 9999, 3907db96d56Sopenharmony_ci self.cid, 3917db96d56Sopenharmony_ci ]) 3927db96d56Sopenharmony_ci 3937db96d56Sopenharmony_ci def test_bytes(self): 3947db96d56Sopenharmony_ci self._assert_values(i.to_bytes(2, 'little', signed=True) 3957db96d56Sopenharmony_ci for i in range(-1, 258)) 3967db96d56Sopenharmony_ci 3977db96d56Sopenharmony_ci def test_strs(self): 3987db96d56Sopenharmony_ci self._assert_values(['hello world', '你好世界', '']) 3997db96d56Sopenharmony_ci 4007db96d56Sopenharmony_ci def test_int(self): 4017db96d56Sopenharmony_ci self._assert_values(itertools.chain(range(-1, 258), 4027db96d56Sopenharmony_ci [sys.maxsize, -sys.maxsize - 1])) 4037db96d56Sopenharmony_ci 4047db96d56Sopenharmony_ci def test_non_shareable_int(self): 4057db96d56Sopenharmony_ci ints = [ 4067db96d56Sopenharmony_ci sys.maxsize + 1, 4077db96d56Sopenharmony_ci -sys.maxsize - 2, 4087db96d56Sopenharmony_ci 2**1000, 4097db96d56Sopenharmony_ci ] 4107db96d56Sopenharmony_ci for i in ints: 4117db96d56Sopenharmony_ci with self.subTest(i): 4127db96d56Sopenharmony_ci with self.assertRaises(OverflowError): 4137db96d56Sopenharmony_ci interpreters.channel_send(self.cid, i) 4147db96d56Sopenharmony_ci 4157db96d56Sopenharmony_ci 4167db96d56Sopenharmony_ci################################## 4177db96d56Sopenharmony_ci# interpreter tests 4187db96d56Sopenharmony_ci 4197db96d56Sopenharmony_ciclass ListAllTests(TestBase): 4207db96d56Sopenharmony_ci 4217db96d56Sopenharmony_ci def test_initial(self): 4227db96d56Sopenharmony_ci main = interpreters.get_main() 4237db96d56Sopenharmony_ci ids = interpreters.list_all() 4247db96d56Sopenharmony_ci self.assertEqual(ids, [main]) 4257db96d56Sopenharmony_ci 4267db96d56Sopenharmony_ci def test_after_creating(self): 4277db96d56Sopenharmony_ci main = interpreters.get_main() 4287db96d56Sopenharmony_ci first = interpreters.create() 4297db96d56Sopenharmony_ci second = interpreters.create() 4307db96d56Sopenharmony_ci ids = interpreters.list_all() 4317db96d56Sopenharmony_ci self.assertEqual(ids, [main, first, second]) 4327db96d56Sopenharmony_ci 4337db96d56Sopenharmony_ci def test_after_destroying(self): 4347db96d56Sopenharmony_ci main = interpreters.get_main() 4357db96d56Sopenharmony_ci first = interpreters.create() 4367db96d56Sopenharmony_ci second = interpreters.create() 4377db96d56Sopenharmony_ci interpreters.destroy(first) 4387db96d56Sopenharmony_ci ids = interpreters.list_all() 4397db96d56Sopenharmony_ci self.assertEqual(ids, [main, second]) 4407db96d56Sopenharmony_ci 4417db96d56Sopenharmony_ci 4427db96d56Sopenharmony_ciclass GetCurrentTests(TestBase): 4437db96d56Sopenharmony_ci 4447db96d56Sopenharmony_ci def test_main(self): 4457db96d56Sopenharmony_ci main = interpreters.get_main() 4467db96d56Sopenharmony_ci cur = interpreters.get_current() 4477db96d56Sopenharmony_ci self.assertEqual(cur, main) 4487db96d56Sopenharmony_ci self.assertIsInstance(cur, interpreters.InterpreterID) 4497db96d56Sopenharmony_ci 4507db96d56Sopenharmony_ci def test_subinterpreter(self): 4517db96d56Sopenharmony_ci main = interpreters.get_main() 4527db96d56Sopenharmony_ci interp = interpreters.create() 4537db96d56Sopenharmony_ci out = _run_output(interp, dedent(""" 4547db96d56Sopenharmony_ci import _xxsubinterpreters as _interpreters 4557db96d56Sopenharmony_ci cur = _interpreters.get_current() 4567db96d56Sopenharmony_ci print(cur) 4577db96d56Sopenharmony_ci assert isinstance(cur, _interpreters.InterpreterID) 4587db96d56Sopenharmony_ci """)) 4597db96d56Sopenharmony_ci cur = int(out.strip()) 4607db96d56Sopenharmony_ci _, expected = interpreters.list_all() 4617db96d56Sopenharmony_ci self.assertEqual(cur, expected) 4627db96d56Sopenharmony_ci self.assertNotEqual(cur, main) 4637db96d56Sopenharmony_ci 4647db96d56Sopenharmony_ci 4657db96d56Sopenharmony_ciclass GetMainTests(TestBase): 4667db96d56Sopenharmony_ci 4677db96d56Sopenharmony_ci def test_from_main(self): 4687db96d56Sopenharmony_ci [expected] = interpreters.list_all() 4697db96d56Sopenharmony_ci main = interpreters.get_main() 4707db96d56Sopenharmony_ci self.assertEqual(main, expected) 4717db96d56Sopenharmony_ci self.assertIsInstance(main, interpreters.InterpreterID) 4727db96d56Sopenharmony_ci 4737db96d56Sopenharmony_ci def test_from_subinterpreter(self): 4747db96d56Sopenharmony_ci [expected] = interpreters.list_all() 4757db96d56Sopenharmony_ci interp = interpreters.create() 4767db96d56Sopenharmony_ci out = _run_output(interp, dedent(""" 4777db96d56Sopenharmony_ci import _xxsubinterpreters as _interpreters 4787db96d56Sopenharmony_ci main = _interpreters.get_main() 4797db96d56Sopenharmony_ci print(main) 4807db96d56Sopenharmony_ci assert isinstance(main, _interpreters.InterpreterID) 4817db96d56Sopenharmony_ci """)) 4827db96d56Sopenharmony_ci main = int(out.strip()) 4837db96d56Sopenharmony_ci self.assertEqual(main, expected) 4847db96d56Sopenharmony_ci 4857db96d56Sopenharmony_ci 4867db96d56Sopenharmony_ciclass IsRunningTests(TestBase): 4877db96d56Sopenharmony_ci 4887db96d56Sopenharmony_ci def test_main(self): 4897db96d56Sopenharmony_ci main = interpreters.get_main() 4907db96d56Sopenharmony_ci self.assertTrue(interpreters.is_running(main)) 4917db96d56Sopenharmony_ci 4927db96d56Sopenharmony_ci @unittest.skip('Fails on FreeBSD') 4937db96d56Sopenharmony_ci def test_subinterpreter(self): 4947db96d56Sopenharmony_ci interp = interpreters.create() 4957db96d56Sopenharmony_ci self.assertFalse(interpreters.is_running(interp)) 4967db96d56Sopenharmony_ci 4977db96d56Sopenharmony_ci with _running(interp): 4987db96d56Sopenharmony_ci self.assertTrue(interpreters.is_running(interp)) 4997db96d56Sopenharmony_ci self.assertFalse(interpreters.is_running(interp)) 5007db96d56Sopenharmony_ci 5017db96d56Sopenharmony_ci def test_from_subinterpreter(self): 5027db96d56Sopenharmony_ci interp = interpreters.create() 5037db96d56Sopenharmony_ci out = _run_output(interp, dedent(f""" 5047db96d56Sopenharmony_ci import _xxsubinterpreters as _interpreters 5057db96d56Sopenharmony_ci if _interpreters.is_running({interp}): 5067db96d56Sopenharmony_ci print(True) 5077db96d56Sopenharmony_ci else: 5087db96d56Sopenharmony_ci print(False) 5097db96d56Sopenharmony_ci """)) 5107db96d56Sopenharmony_ci self.assertEqual(out.strip(), 'True') 5117db96d56Sopenharmony_ci 5127db96d56Sopenharmony_ci def test_already_destroyed(self): 5137db96d56Sopenharmony_ci interp = interpreters.create() 5147db96d56Sopenharmony_ci interpreters.destroy(interp) 5157db96d56Sopenharmony_ci with self.assertRaises(RuntimeError): 5167db96d56Sopenharmony_ci interpreters.is_running(interp) 5177db96d56Sopenharmony_ci 5187db96d56Sopenharmony_ci def test_does_not_exist(self): 5197db96d56Sopenharmony_ci with self.assertRaises(RuntimeError): 5207db96d56Sopenharmony_ci interpreters.is_running(1_000_000) 5217db96d56Sopenharmony_ci 5227db96d56Sopenharmony_ci def test_bad_id(self): 5237db96d56Sopenharmony_ci with self.assertRaises(ValueError): 5247db96d56Sopenharmony_ci interpreters.is_running(-1) 5257db96d56Sopenharmony_ci 5267db96d56Sopenharmony_ci 5277db96d56Sopenharmony_ciclass InterpreterIDTests(TestBase): 5287db96d56Sopenharmony_ci 5297db96d56Sopenharmony_ci def test_with_int(self): 5307db96d56Sopenharmony_ci id = interpreters.InterpreterID(10, force=True) 5317db96d56Sopenharmony_ci 5327db96d56Sopenharmony_ci self.assertEqual(int(id), 10) 5337db96d56Sopenharmony_ci 5347db96d56Sopenharmony_ci def test_coerce_id(self): 5357db96d56Sopenharmony_ci class Int(str): 5367db96d56Sopenharmony_ci def __index__(self): 5377db96d56Sopenharmony_ci return 10 5387db96d56Sopenharmony_ci 5397db96d56Sopenharmony_ci id = interpreters.InterpreterID(Int(), force=True) 5407db96d56Sopenharmony_ci self.assertEqual(int(id), 10) 5417db96d56Sopenharmony_ci 5427db96d56Sopenharmony_ci def test_bad_id(self): 5437db96d56Sopenharmony_ci self.assertRaises(TypeError, interpreters.InterpreterID, object()) 5447db96d56Sopenharmony_ci self.assertRaises(TypeError, interpreters.InterpreterID, 10.0) 5457db96d56Sopenharmony_ci self.assertRaises(TypeError, interpreters.InterpreterID, '10') 5467db96d56Sopenharmony_ci self.assertRaises(TypeError, interpreters.InterpreterID, b'10') 5477db96d56Sopenharmony_ci self.assertRaises(ValueError, interpreters.InterpreterID, -1) 5487db96d56Sopenharmony_ci self.assertRaises(OverflowError, interpreters.InterpreterID, 2**64) 5497db96d56Sopenharmony_ci 5507db96d56Sopenharmony_ci def test_does_not_exist(self): 5517db96d56Sopenharmony_ci id = interpreters.channel_create() 5527db96d56Sopenharmony_ci with self.assertRaises(RuntimeError): 5537db96d56Sopenharmony_ci interpreters.InterpreterID(int(id) + 1) # unforced 5547db96d56Sopenharmony_ci 5557db96d56Sopenharmony_ci def test_str(self): 5567db96d56Sopenharmony_ci id = interpreters.InterpreterID(10, force=True) 5577db96d56Sopenharmony_ci self.assertEqual(str(id), '10') 5587db96d56Sopenharmony_ci 5597db96d56Sopenharmony_ci def test_repr(self): 5607db96d56Sopenharmony_ci id = interpreters.InterpreterID(10, force=True) 5617db96d56Sopenharmony_ci self.assertEqual(repr(id), 'InterpreterID(10)') 5627db96d56Sopenharmony_ci 5637db96d56Sopenharmony_ci def test_equality(self): 5647db96d56Sopenharmony_ci id1 = interpreters.create() 5657db96d56Sopenharmony_ci id2 = interpreters.InterpreterID(int(id1)) 5667db96d56Sopenharmony_ci id3 = interpreters.create() 5677db96d56Sopenharmony_ci 5687db96d56Sopenharmony_ci self.assertTrue(id1 == id1) 5697db96d56Sopenharmony_ci self.assertTrue(id1 == id2) 5707db96d56Sopenharmony_ci self.assertTrue(id1 == int(id1)) 5717db96d56Sopenharmony_ci self.assertTrue(int(id1) == id1) 5727db96d56Sopenharmony_ci self.assertTrue(id1 == float(int(id1))) 5737db96d56Sopenharmony_ci self.assertTrue(float(int(id1)) == id1) 5747db96d56Sopenharmony_ci self.assertFalse(id1 == float(int(id1)) + 0.1) 5757db96d56Sopenharmony_ci self.assertFalse(id1 == str(int(id1))) 5767db96d56Sopenharmony_ci self.assertFalse(id1 == 2**1000) 5777db96d56Sopenharmony_ci self.assertFalse(id1 == float('inf')) 5787db96d56Sopenharmony_ci self.assertFalse(id1 == 'spam') 5797db96d56Sopenharmony_ci self.assertFalse(id1 == id3) 5807db96d56Sopenharmony_ci 5817db96d56Sopenharmony_ci self.assertFalse(id1 != id1) 5827db96d56Sopenharmony_ci self.assertFalse(id1 != id2) 5837db96d56Sopenharmony_ci self.assertTrue(id1 != id3) 5847db96d56Sopenharmony_ci 5857db96d56Sopenharmony_ci 5867db96d56Sopenharmony_ciclass CreateTests(TestBase): 5877db96d56Sopenharmony_ci 5887db96d56Sopenharmony_ci def test_in_main(self): 5897db96d56Sopenharmony_ci id = interpreters.create() 5907db96d56Sopenharmony_ci self.assertIsInstance(id, interpreters.InterpreterID) 5917db96d56Sopenharmony_ci 5927db96d56Sopenharmony_ci self.assertIn(id, interpreters.list_all()) 5937db96d56Sopenharmony_ci 5947db96d56Sopenharmony_ci @unittest.skip('enable this test when working on pystate.c') 5957db96d56Sopenharmony_ci def test_unique_id(self): 5967db96d56Sopenharmony_ci seen = set() 5977db96d56Sopenharmony_ci for _ in range(100): 5987db96d56Sopenharmony_ci id = interpreters.create() 5997db96d56Sopenharmony_ci interpreters.destroy(id) 6007db96d56Sopenharmony_ci seen.add(id) 6017db96d56Sopenharmony_ci 6027db96d56Sopenharmony_ci self.assertEqual(len(seen), 100) 6037db96d56Sopenharmony_ci 6047db96d56Sopenharmony_ci def test_in_thread(self): 6057db96d56Sopenharmony_ci lock = threading.Lock() 6067db96d56Sopenharmony_ci id = None 6077db96d56Sopenharmony_ci def f(): 6087db96d56Sopenharmony_ci nonlocal id 6097db96d56Sopenharmony_ci id = interpreters.create() 6107db96d56Sopenharmony_ci lock.acquire() 6117db96d56Sopenharmony_ci lock.release() 6127db96d56Sopenharmony_ci 6137db96d56Sopenharmony_ci t = threading.Thread(target=f) 6147db96d56Sopenharmony_ci with lock: 6157db96d56Sopenharmony_ci t.start() 6167db96d56Sopenharmony_ci t.join() 6177db96d56Sopenharmony_ci self.assertIn(id, interpreters.list_all()) 6187db96d56Sopenharmony_ci 6197db96d56Sopenharmony_ci def test_in_subinterpreter(self): 6207db96d56Sopenharmony_ci main, = interpreters.list_all() 6217db96d56Sopenharmony_ci id1 = interpreters.create() 6227db96d56Sopenharmony_ci out = _run_output(id1, dedent(""" 6237db96d56Sopenharmony_ci import _xxsubinterpreters as _interpreters 6247db96d56Sopenharmony_ci id = _interpreters.create() 6257db96d56Sopenharmony_ci print(id) 6267db96d56Sopenharmony_ci assert isinstance(id, _interpreters.InterpreterID) 6277db96d56Sopenharmony_ci """)) 6287db96d56Sopenharmony_ci id2 = int(out.strip()) 6297db96d56Sopenharmony_ci 6307db96d56Sopenharmony_ci self.assertEqual(set(interpreters.list_all()), {main, id1, id2}) 6317db96d56Sopenharmony_ci 6327db96d56Sopenharmony_ci def test_in_threaded_subinterpreter(self): 6337db96d56Sopenharmony_ci main, = interpreters.list_all() 6347db96d56Sopenharmony_ci id1 = interpreters.create() 6357db96d56Sopenharmony_ci id2 = None 6367db96d56Sopenharmony_ci def f(): 6377db96d56Sopenharmony_ci nonlocal id2 6387db96d56Sopenharmony_ci out = _run_output(id1, dedent(""" 6397db96d56Sopenharmony_ci import _xxsubinterpreters as _interpreters 6407db96d56Sopenharmony_ci id = _interpreters.create() 6417db96d56Sopenharmony_ci print(id) 6427db96d56Sopenharmony_ci """)) 6437db96d56Sopenharmony_ci id2 = int(out.strip()) 6447db96d56Sopenharmony_ci 6457db96d56Sopenharmony_ci t = threading.Thread(target=f) 6467db96d56Sopenharmony_ci t.start() 6477db96d56Sopenharmony_ci t.join() 6487db96d56Sopenharmony_ci 6497db96d56Sopenharmony_ci self.assertEqual(set(interpreters.list_all()), {main, id1, id2}) 6507db96d56Sopenharmony_ci 6517db96d56Sopenharmony_ci def test_after_destroy_all(self): 6527db96d56Sopenharmony_ci before = set(interpreters.list_all()) 6537db96d56Sopenharmony_ci # Create 3 subinterpreters. 6547db96d56Sopenharmony_ci ids = [] 6557db96d56Sopenharmony_ci for _ in range(3): 6567db96d56Sopenharmony_ci id = interpreters.create() 6577db96d56Sopenharmony_ci ids.append(id) 6587db96d56Sopenharmony_ci # Now destroy them. 6597db96d56Sopenharmony_ci for id in ids: 6607db96d56Sopenharmony_ci interpreters.destroy(id) 6617db96d56Sopenharmony_ci # Finally, create another. 6627db96d56Sopenharmony_ci id = interpreters.create() 6637db96d56Sopenharmony_ci self.assertEqual(set(interpreters.list_all()), before | {id}) 6647db96d56Sopenharmony_ci 6657db96d56Sopenharmony_ci def test_after_destroy_some(self): 6667db96d56Sopenharmony_ci before = set(interpreters.list_all()) 6677db96d56Sopenharmony_ci # Create 3 subinterpreters. 6687db96d56Sopenharmony_ci id1 = interpreters.create() 6697db96d56Sopenharmony_ci id2 = interpreters.create() 6707db96d56Sopenharmony_ci id3 = interpreters.create() 6717db96d56Sopenharmony_ci # Now destroy 2 of them. 6727db96d56Sopenharmony_ci interpreters.destroy(id1) 6737db96d56Sopenharmony_ci interpreters.destroy(id3) 6747db96d56Sopenharmony_ci # Finally, create another. 6757db96d56Sopenharmony_ci id = interpreters.create() 6767db96d56Sopenharmony_ci self.assertEqual(set(interpreters.list_all()), before | {id, id2}) 6777db96d56Sopenharmony_ci 6787db96d56Sopenharmony_ci 6797db96d56Sopenharmony_ciclass DestroyTests(TestBase): 6807db96d56Sopenharmony_ci 6817db96d56Sopenharmony_ci def test_one(self): 6827db96d56Sopenharmony_ci id1 = interpreters.create() 6837db96d56Sopenharmony_ci id2 = interpreters.create() 6847db96d56Sopenharmony_ci id3 = interpreters.create() 6857db96d56Sopenharmony_ci self.assertIn(id2, interpreters.list_all()) 6867db96d56Sopenharmony_ci interpreters.destroy(id2) 6877db96d56Sopenharmony_ci self.assertNotIn(id2, interpreters.list_all()) 6887db96d56Sopenharmony_ci self.assertIn(id1, interpreters.list_all()) 6897db96d56Sopenharmony_ci self.assertIn(id3, interpreters.list_all()) 6907db96d56Sopenharmony_ci 6917db96d56Sopenharmony_ci def test_all(self): 6927db96d56Sopenharmony_ci before = set(interpreters.list_all()) 6937db96d56Sopenharmony_ci ids = set() 6947db96d56Sopenharmony_ci for _ in range(3): 6957db96d56Sopenharmony_ci id = interpreters.create() 6967db96d56Sopenharmony_ci ids.add(id) 6977db96d56Sopenharmony_ci self.assertEqual(set(interpreters.list_all()), before | ids) 6987db96d56Sopenharmony_ci for id in ids: 6997db96d56Sopenharmony_ci interpreters.destroy(id) 7007db96d56Sopenharmony_ci self.assertEqual(set(interpreters.list_all()), before) 7017db96d56Sopenharmony_ci 7027db96d56Sopenharmony_ci def test_main(self): 7037db96d56Sopenharmony_ci main, = interpreters.list_all() 7047db96d56Sopenharmony_ci with self.assertRaises(RuntimeError): 7057db96d56Sopenharmony_ci interpreters.destroy(main) 7067db96d56Sopenharmony_ci 7077db96d56Sopenharmony_ci def f(): 7087db96d56Sopenharmony_ci with self.assertRaises(RuntimeError): 7097db96d56Sopenharmony_ci interpreters.destroy(main) 7107db96d56Sopenharmony_ci 7117db96d56Sopenharmony_ci t = threading.Thread(target=f) 7127db96d56Sopenharmony_ci t.start() 7137db96d56Sopenharmony_ci t.join() 7147db96d56Sopenharmony_ci 7157db96d56Sopenharmony_ci def test_already_destroyed(self): 7167db96d56Sopenharmony_ci id = interpreters.create() 7177db96d56Sopenharmony_ci interpreters.destroy(id) 7187db96d56Sopenharmony_ci with self.assertRaises(RuntimeError): 7197db96d56Sopenharmony_ci interpreters.destroy(id) 7207db96d56Sopenharmony_ci 7217db96d56Sopenharmony_ci def test_does_not_exist(self): 7227db96d56Sopenharmony_ci with self.assertRaises(RuntimeError): 7237db96d56Sopenharmony_ci interpreters.destroy(1_000_000) 7247db96d56Sopenharmony_ci 7257db96d56Sopenharmony_ci def test_bad_id(self): 7267db96d56Sopenharmony_ci with self.assertRaises(ValueError): 7277db96d56Sopenharmony_ci interpreters.destroy(-1) 7287db96d56Sopenharmony_ci 7297db96d56Sopenharmony_ci def test_from_current(self): 7307db96d56Sopenharmony_ci main, = interpreters.list_all() 7317db96d56Sopenharmony_ci id = interpreters.create() 7327db96d56Sopenharmony_ci script = dedent(f""" 7337db96d56Sopenharmony_ci import _xxsubinterpreters as _interpreters 7347db96d56Sopenharmony_ci try: 7357db96d56Sopenharmony_ci _interpreters.destroy({id}) 7367db96d56Sopenharmony_ci except RuntimeError: 7377db96d56Sopenharmony_ci pass 7387db96d56Sopenharmony_ci """) 7397db96d56Sopenharmony_ci 7407db96d56Sopenharmony_ci interpreters.run_string(id, script) 7417db96d56Sopenharmony_ci self.assertEqual(set(interpreters.list_all()), {main, id}) 7427db96d56Sopenharmony_ci 7437db96d56Sopenharmony_ci def test_from_sibling(self): 7447db96d56Sopenharmony_ci main, = interpreters.list_all() 7457db96d56Sopenharmony_ci id1 = interpreters.create() 7467db96d56Sopenharmony_ci id2 = interpreters.create() 7477db96d56Sopenharmony_ci script = dedent(f""" 7487db96d56Sopenharmony_ci import _xxsubinterpreters as _interpreters 7497db96d56Sopenharmony_ci _interpreters.destroy({id2}) 7507db96d56Sopenharmony_ci """) 7517db96d56Sopenharmony_ci interpreters.run_string(id1, script) 7527db96d56Sopenharmony_ci 7537db96d56Sopenharmony_ci self.assertEqual(set(interpreters.list_all()), {main, id1}) 7547db96d56Sopenharmony_ci 7557db96d56Sopenharmony_ci def test_from_other_thread(self): 7567db96d56Sopenharmony_ci id = interpreters.create() 7577db96d56Sopenharmony_ci def f(): 7587db96d56Sopenharmony_ci interpreters.destroy(id) 7597db96d56Sopenharmony_ci 7607db96d56Sopenharmony_ci t = threading.Thread(target=f) 7617db96d56Sopenharmony_ci t.start() 7627db96d56Sopenharmony_ci t.join() 7637db96d56Sopenharmony_ci 7647db96d56Sopenharmony_ci def test_still_running(self): 7657db96d56Sopenharmony_ci main, = interpreters.list_all() 7667db96d56Sopenharmony_ci interp = interpreters.create() 7677db96d56Sopenharmony_ci with _running(interp): 7687db96d56Sopenharmony_ci self.assertTrue(interpreters.is_running(interp), 7697db96d56Sopenharmony_ci msg=f"Interp {interp} should be running before destruction.") 7707db96d56Sopenharmony_ci 7717db96d56Sopenharmony_ci with self.assertRaises(RuntimeError, 7727db96d56Sopenharmony_ci msg=f"Should not be able to destroy interp {interp} while it's still running."): 7737db96d56Sopenharmony_ci interpreters.destroy(interp) 7747db96d56Sopenharmony_ci self.assertTrue(interpreters.is_running(interp)) 7757db96d56Sopenharmony_ci 7767db96d56Sopenharmony_ci 7777db96d56Sopenharmony_ciclass RunStringTests(TestBase): 7787db96d56Sopenharmony_ci 7797db96d56Sopenharmony_ci def setUp(self): 7807db96d56Sopenharmony_ci super().setUp() 7817db96d56Sopenharmony_ci self.id = interpreters.create() 7827db96d56Sopenharmony_ci 7837db96d56Sopenharmony_ci def test_success(self): 7847db96d56Sopenharmony_ci script, file = _captured_script('print("it worked!", end="")') 7857db96d56Sopenharmony_ci with file: 7867db96d56Sopenharmony_ci interpreters.run_string(self.id, script) 7877db96d56Sopenharmony_ci out = file.read() 7887db96d56Sopenharmony_ci 7897db96d56Sopenharmony_ci self.assertEqual(out, 'it worked!') 7907db96d56Sopenharmony_ci 7917db96d56Sopenharmony_ci def test_in_thread(self): 7927db96d56Sopenharmony_ci script, file = _captured_script('print("it worked!", end="")') 7937db96d56Sopenharmony_ci with file: 7947db96d56Sopenharmony_ci def f(): 7957db96d56Sopenharmony_ci interpreters.run_string(self.id, script) 7967db96d56Sopenharmony_ci 7977db96d56Sopenharmony_ci t = threading.Thread(target=f) 7987db96d56Sopenharmony_ci t.start() 7997db96d56Sopenharmony_ci t.join() 8007db96d56Sopenharmony_ci out = file.read() 8017db96d56Sopenharmony_ci 8027db96d56Sopenharmony_ci self.assertEqual(out, 'it worked!') 8037db96d56Sopenharmony_ci 8047db96d56Sopenharmony_ci def test_create_thread(self): 8057db96d56Sopenharmony_ci subinterp = interpreters.create(isolated=False) 8067db96d56Sopenharmony_ci script, file = _captured_script(""" 8077db96d56Sopenharmony_ci import threading 8087db96d56Sopenharmony_ci def f(): 8097db96d56Sopenharmony_ci print('it worked!', end='') 8107db96d56Sopenharmony_ci 8117db96d56Sopenharmony_ci t = threading.Thread(target=f) 8127db96d56Sopenharmony_ci t.start() 8137db96d56Sopenharmony_ci t.join() 8147db96d56Sopenharmony_ci """) 8157db96d56Sopenharmony_ci with file: 8167db96d56Sopenharmony_ci interpreters.run_string(subinterp, script) 8177db96d56Sopenharmony_ci out = file.read() 8187db96d56Sopenharmony_ci 8197db96d56Sopenharmony_ci self.assertEqual(out, 'it worked!') 8207db96d56Sopenharmony_ci 8217db96d56Sopenharmony_ci @support.requires_fork() 8227db96d56Sopenharmony_ci def test_fork(self): 8237db96d56Sopenharmony_ci import tempfile 8247db96d56Sopenharmony_ci with tempfile.NamedTemporaryFile('w+', encoding="utf-8") as file: 8257db96d56Sopenharmony_ci file.write('') 8267db96d56Sopenharmony_ci file.flush() 8277db96d56Sopenharmony_ci 8287db96d56Sopenharmony_ci expected = 'spam spam spam spam spam' 8297db96d56Sopenharmony_ci script = dedent(f""" 8307db96d56Sopenharmony_ci import os 8317db96d56Sopenharmony_ci try: 8327db96d56Sopenharmony_ci os.fork() 8337db96d56Sopenharmony_ci except RuntimeError: 8347db96d56Sopenharmony_ci with open('{file.name}', 'w', encoding='utf-8') as out: 8357db96d56Sopenharmony_ci out.write('{expected}') 8367db96d56Sopenharmony_ci """) 8377db96d56Sopenharmony_ci interpreters.run_string(self.id, script) 8387db96d56Sopenharmony_ci 8397db96d56Sopenharmony_ci file.seek(0) 8407db96d56Sopenharmony_ci content = file.read() 8417db96d56Sopenharmony_ci self.assertEqual(content, expected) 8427db96d56Sopenharmony_ci 8437db96d56Sopenharmony_ci def test_already_running(self): 8447db96d56Sopenharmony_ci with _running(self.id): 8457db96d56Sopenharmony_ci with self.assertRaises(RuntimeError): 8467db96d56Sopenharmony_ci interpreters.run_string(self.id, 'print("spam")') 8477db96d56Sopenharmony_ci 8487db96d56Sopenharmony_ci def test_does_not_exist(self): 8497db96d56Sopenharmony_ci id = 0 8507db96d56Sopenharmony_ci while id in interpreters.list_all(): 8517db96d56Sopenharmony_ci id += 1 8527db96d56Sopenharmony_ci with self.assertRaises(RuntimeError): 8537db96d56Sopenharmony_ci interpreters.run_string(id, 'print("spam")') 8547db96d56Sopenharmony_ci 8557db96d56Sopenharmony_ci def test_error_id(self): 8567db96d56Sopenharmony_ci with self.assertRaises(ValueError): 8577db96d56Sopenharmony_ci interpreters.run_string(-1, 'print("spam")') 8587db96d56Sopenharmony_ci 8597db96d56Sopenharmony_ci def test_bad_id(self): 8607db96d56Sopenharmony_ci with self.assertRaises(TypeError): 8617db96d56Sopenharmony_ci interpreters.run_string('spam', 'print("spam")') 8627db96d56Sopenharmony_ci 8637db96d56Sopenharmony_ci def test_bad_script(self): 8647db96d56Sopenharmony_ci with self.assertRaises(TypeError): 8657db96d56Sopenharmony_ci interpreters.run_string(self.id, 10) 8667db96d56Sopenharmony_ci 8677db96d56Sopenharmony_ci def test_bytes_for_script(self): 8687db96d56Sopenharmony_ci with self.assertRaises(TypeError): 8697db96d56Sopenharmony_ci interpreters.run_string(self.id, b'print("spam")') 8707db96d56Sopenharmony_ci 8717db96d56Sopenharmony_ci @contextlib.contextmanager 8727db96d56Sopenharmony_ci def assert_run_failed(self, exctype, msg=None): 8737db96d56Sopenharmony_ci with self.assertRaises(interpreters.RunFailedError) as caught: 8747db96d56Sopenharmony_ci yield 8757db96d56Sopenharmony_ci if msg is None: 8767db96d56Sopenharmony_ci self.assertEqual(str(caught.exception).split(':')[0], 8777db96d56Sopenharmony_ci str(exctype)) 8787db96d56Sopenharmony_ci else: 8797db96d56Sopenharmony_ci self.assertEqual(str(caught.exception), 8807db96d56Sopenharmony_ci "{}: {}".format(exctype, msg)) 8817db96d56Sopenharmony_ci 8827db96d56Sopenharmony_ci def test_invalid_syntax(self): 8837db96d56Sopenharmony_ci with self.assert_run_failed(SyntaxError): 8847db96d56Sopenharmony_ci # missing close paren 8857db96d56Sopenharmony_ci interpreters.run_string(self.id, 'print("spam"') 8867db96d56Sopenharmony_ci 8877db96d56Sopenharmony_ci def test_failure(self): 8887db96d56Sopenharmony_ci with self.assert_run_failed(Exception, 'spam'): 8897db96d56Sopenharmony_ci interpreters.run_string(self.id, 'raise Exception("spam")') 8907db96d56Sopenharmony_ci 8917db96d56Sopenharmony_ci def test_SystemExit(self): 8927db96d56Sopenharmony_ci with self.assert_run_failed(SystemExit, '42'): 8937db96d56Sopenharmony_ci interpreters.run_string(self.id, 'raise SystemExit(42)') 8947db96d56Sopenharmony_ci 8957db96d56Sopenharmony_ci def test_sys_exit(self): 8967db96d56Sopenharmony_ci with self.assert_run_failed(SystemExit): 8977db96d56Sopenharmony_ci interpreters.run_string(self.id, dedent(""" 8987db96d56Sopenharmony_ci import sys 8997db96d56Sopenharmony_ci sys.exit() 9007db96d56Sopenharmony_ci """)) 9017db96d56Sopenharmony_ci 9027db96d56Sopenharmony_ci with self.assert_run_failed(SystemExit, '42'): 9037db96d56Sopenharmony_ci interpreters.run_string(self.id, dedent(""" 9047db96d56Sopenharmony_ci import sys 9057db96d56Sopenharmony_ci sys.exit(42) 9067db96d56Sopenharmony_ci """)) 9077db96d56Sopenharmony_ci 9087db96d56Sopenharmony_ci def test_with_shared(self): 9097db96d56Sopenharmony_ci r, w = os.pipe() 9107db96d56Sopenharmony_ci 9117db96d56Sopenharmony_ci shared = { 9127db96d56Sopenharmony_ci 'spam': b'ham', 9137db96d56Sopenharmony_ci 'eggs': b'-1', 9147db96d56Sopenharmony_ci 'cheddar': None, 9157db96d56Sopenharmony_ci } 9167db96d56Sopenharmony_ci script = dedent(f""" 9177db96d56Sopenharmony_ci eggs = int(eggs) 9187db96d56Sopenharmony_ci spam = 42 9197db96d56Sopenharmony_ci result = spam + eggs 9207db96d56Sopenharmony_ci 9217db96d56Sopenharmony_ci ns = dict(vars()) 9227db96d56Sopenharmony_ci del ns['__builtins__'] 9237db96d56Sopenharmony_ci import pickle 9247db96d56Sopenharmony_ci with open({w}, 'wb') as chan: 9257db96d56Sopenharmony_ci pickle.dump(ns, chan) 9267db96d56Sopenharmony_ci """) 9277db96d56Sopenharmony_ci interpreters.run_string(self.id, script, shared) 9287db96d56Sopenharmony_ci with open(r, 'rb') as chan: 9297db96d56Sopenharmony_ci ns = pickle.load(chan) 9307db96d56Sopenharmony_ci 9317db96d56Sopenharmony_ci self.assertEqual(ns['spam'], 42) 9327db96d56Sopenharmony_ci self.assertEqual(ns['eggs'], -1) 9337db96d56Sopenharmony_ci self.assertEqual(ns['result'], 41) 9347db96d56Sopenharmony_ci self.assertIsNone(ns['cheddar']) 9357db96d56Sopenharmony_ci 9367db96d56Sopenharmony_ci def test_shared_overwrites(self): 9377db96d56Sopenharmony_ci interpreters.run_string(self.id, dedent(""" 9387db96d56Sopenharmony_ci spam = 'eggs' 9397db96d56Sopenharmony_ci ns1 = dict(vars()) 9407db96d56Sopenharmony_ci del ns1['__builtins__'] 9417db96d56Sopenharmony_ci """)) 9427db96d56Sopenharmony_ci 9437db96d56Sopenharmony_ci shared = {'spam': b'ham'} 9447db96d56Sopenharmony_ci script = dedent(f""" 9457db96d56Sopenharmony_ci ns2 = dict(vars()) 9467db96d56Sopenharmony_ci del ns2['__builtins__'] 9477db96d56Sopenharmony_ci """) 9487db96d56Sopenharmony_ci interpreters.run_string(self.id, script, shared) 9497db96d56Sopenharmony_ci 9507db96d56Sopenharmony_ci r, w = os.pipe() 9517db96d56Sopenharmony_ci script = dedent(f""" 9527db96d56Sopenharmony_ci ns = dict(vars()) 9537db96d56Sopenharmony_ci del ns['__builtins__'] 9547db96d56Sopenharmony_ci import pickle 9557db96d56Sopenharmony_ci with open({w}, 'wb') as chan: 9567db96d56Sopenharmony_ci pickle.dump(ns, chan) 9577db96d56Sopenharmony_ci """) 9587db96d56Sopenharmony_ci interpreters.run_string(self.id, script) 9597db96d56Sopenharmony_ci with open(r, 'rb') as chan: 9607db96d56Sopenharmony_ci ns = pickle.load(chan) 9617db96d56Sopenharmony_ci 9627db96d56Sopenharmony_ci self.assertEqual(ns['ns1']['spam'], 'eggs') 9637db96d56Sopenharmony_ci self.assertEqual(ns['ns2']['spam'], b'ham') 9647db96d56Sopenharmony_ci self.assertEqual(ns['spam'], b'ham') 9657db96d56Sopenharmony_ci 9667db96d56Sopenharmony_ci def test_shared_overwrites_default_vars(self): 9677db96d56Sopenharmony_ci r, w = os.pipe() 9687db96d56Sopenharmony_ci 9697db96d56Sopenharmony_ci shared = {'__name__': b'not __main__'} 9707db96d56Sopenharmony_ci script = dedent(f""" 9717db96d56Sopenharmony_ci spam = 42 9727db96d56Sopenharmony_ci 9737db96d56Sopenharmony_ci ns = dict(vars()) 9747db96d56Sopenharmony_ci del ns['__builtins__'] 9757db96d56Sopenharmony_ci import pickle 9767db96d56Sopenharmony_ci with open({w}, 'wb') as chan: 9777db96d56Sopenharmony_ci pickle.dump(ns, chan) 9787db96d56Sopenharmony_ci """) 9797db96d56Sopenharmony_ci interpreters.run_string(self.id, script, shared) 9807db96d56Sopenharmony_ci with open(r, 'rb') as chan: 9817db96d56Sopenharmony_ci ns = pickle.load(chan) 9827db96d56Sopenharmony_ci 9837db96d56Sopenharmony_ci self.assertEqual(ns['__name__'], b'not __main__') 9847db96d56Sopenharmony_ci 9857db96d56Sopenharmony_ci def test_main_reused(self): 9867db96d56Sopenharmony_ci r, w = os.pipe() 9877db96d56Sopenharmony_ci interpreters.run_string(self.id, dedent(f""" 9887db96d56Sopenharmony_ci spam = True 9897db96d56Sopenharmony_ci 9907db96d56Sopenharmony_ci ns = dict(vars()) 9917db96d56Sopenharmony_ci del ns['__builtins__'] 9927db96d56Sopenharmony_ci import pickle 9937db96d56Sopenharmony_ci with open({w}, 'wb') as chan: 9947db96d56Sopenharmony_ci pickle.dump(ns, chan) 9957db96d56Sopenharmony_ci del ns, pickle, chan 9967db96d56Sopenharmony_ci """)) 9977db96d56Sopenharmony_ci with open(r, 'rb') as chan: 9987db96d56Sopenharmony_ci ns1 = pickle.load(chan) 9997db96d56Sopenharmony_ci 10007db96d56Sopenharmony_ci r, w = os.pipe() 10017db96d56Sopenharmony_ci interpreters.run_string(self.id, dedent(f""" 10027db96d56Sopenharmony_ci eggs = False 10037db96d56Sopenharmony_ci 10047db96d56Sopenharmony_ci ns = dict(vars()) 10057db96d56Sopenharmony_ci del ns['__builtins__'] 10067db96d56Sopenharmony_ci import pickle 10077db96d56Sopenharmony_ci with open({w}, 'wb') as chan: 10087db96d56Sopenharmony_ci pickle.dump(ns, chan) 10097db96d56Sopenharmony_ci """)) 10107db96d56Sopenharmony_ci with open(r, 'rb') as chan: 10117db96d56Sopenharmony_ci ns2 = pickle.load(chan) 10127db96d56Sopenharmony_ci 10137db96d56Sopenharmony_ci self.assertIn('spam', ns1) 10147db96d56Sopenharmony_ci self.assertNotIn('eggs', ns1) 10157db96d56Sopenharmony_ci self.assertIn('eggs', ns2) 10167db96d56Sopenharmony_ci self.assertIn('spam', ns2) 10177db96d56Sopenharmony_ci 10187db96d56Sopenharmony_ci def test_execution_namespace_is_main(self): 10197db96d56Sopenharmony_ci r, w = os.pipe() 10207db96d56Sopenharmony_ci 10217db96d56Sopenharmony_ci script = dedent(f""" 10227db96d56Sopenharmony_ci spam = 42 10237db96d56Sopenharmony_ci 10247db96d56Sopenharmony_ci ns = dict(vars()) 10257db96d56Sopenharmony_ci ns['__builtins__'] = str(ns['__builtins__']) 10267db96d56Sopenharmony_ci import pickle 10277db96d56Sopenharmony_ci with open({w}, 'wb') as chan: 10287db96d56Sopenharmony_ci pickle.dump(ns, chan) 10297db96d56Sopenharmony_ci """) 10307db96d56Sopenharmony_ci interpreters.run_string(self.id, script) 10317db96d56Sopenharmony_ci with open(r, 'rb') as chan: 10327db96d56Sopenharmony_ci ns = pickle.load(chan) 10337db96d56Sopenharmony_ci 10347db96d56Sopenharmony_ci ns.pop('__builtins__') 10357db96d56Sopenharmony_ci ns.pop('__loader__') 10367db96d56Sopenharmony_ci self.assertEqual(ns, { 10377db96d56Sopenharmony_ci '__name__': '__main__', 10387db96d56Sopenharmony_ci '__annotations__': {}, 10397db96d56Sopenharmony_ci '__doc__': None, 10407db96d56Sopenharmony_ci '__package__': None, 10417db96d56Sopenharmony_ci '__spec__': None, 10427db96d56Sopenharmony_ci 'spam': 42, 10437db96d56Sopenharmony_ci }) 10447db96d56Sopenharmony_ci 10457db96d56Sopenharmony_ci # XXX Fix this test! 10467db96d56Sopenharmony_ci @unittest.skip('blocking forever') 10477db96d56Sopenharmony_ci def test_still_running_at_exit(self): 10487db96d56Sopenharmony_ci script = dedent(f""" 10497db96d56Sopenharmony_ci from textwrap import dedent 10507db96d56Sopenharmony_ci import threading 10517db96d56Sopenharmony_ci import _xxsubinterpreters as _interpreters 10527db96d56Sopenharmony_ci id = _interpreters.create() 10537db96d56Sopenharmony_ci def f(): 10547db96d56Sopenharmony_ci _interpreters.run_string(id, dedent(''' 10557db96d56Sopenharmony_ci import time 10567db96d56Sopenharmony_ci # Give plenty of time for the main interpreter to finish. 10577db96d56Sopenharmony_ci time.sleep(1_000_000) 10587db96d56Sopenharmony_ci ''')) 10597db96d56Sopenharmony_ci 10607db96d56Sopenharmony_ci t = threading.Thread(target=f) 10617db96d56Sopenharmony_ci t.start() 10627db96d56Sopenharmony_ci """) 10637db96d56Sopenharmony_ci with support.temp_dir() as dirname: 10647db96d56Sopenharmony_ci filename = script_helper.make_script(dirname, 'interp', script) 10657db96d56Sopenharmony_ci with script_helper.spawn_python(filename) as proc: 10667db96d56Sopenharmony_ci retcode = proc.wait() 10677db96d56Sopenharmony_ci 10687db96d56Sopenharmony_ci self.assertEqual(retcode, 0) 10697db96d56Sopenharmony_ci 10707db96d56Sopenharmony_ci 10717db96d56Sopenharmony_ci################################## 10727db96d56Sopenharmony_ci# channel tests 10737db96d56Sopenharmony_ci 10747db96d56Sopenharmony_ciclass ChannelIDTests(TestBase): 10757db96d56Sopenharmony_ci 10767db96d56Sopenharmony_ci def test_default_kwargs(self): 10777db96d56Sopenharmony_ci cid = interpreters._channel_id(10, force=True) 10787db96d56Sopenharmony_ci 10797db96d56Sopenharmony_ci self.assertEqual(int(cid), 10) 10807db96d56Sopenharmony_ci self.assertEqual(cid.end, 'both') 10817db96d56Sopenharmony_ci 10827db96d56Sopenharmony_ci def test_with_kwargs(self): 10837db96d56Sopenharmony_ci cid = interpreters._channel_id(10, send=True, force=True) 10847db96d56Sopenharmony_ci self.assertEqual(cid.end, 'send') 10857db96d56Sopenharmony_ci 10867db96d56Sopenharmony_ci cid = interpreters._channel_id(10, send=True, recv=False, force=True) 10877db96d56Sopenharmony_ci self.assertEqual(cid.end, 'send') 10887db96d56Sopenharmony_ci 10897db96d56Sopenharmony_ci cid = interpreters._channel_id(10, recv=True, force=True) 10907db96d56Sopenharmony_ci self.assertEqual(cid.end, 'recv') 10917db96d56Sopenharmony_ci 10927db96d56Sopenharmony_ci cid = interpreters._channel_id(10, recv=True, send=False, force=True) 10937db96d56Sopenharmony_ci self.assertEqual(cid.end, 'recv') 10947db96d56Sopenharmony_ci 10957db96d56Sopenharmony_ci cid = interpreters._channel_id(10, send=True, recv=True, force=True) 10967db96d56Sopenharmony_ci self.assertEqual(cid.end, 'both') 10977db96d56Sopenharmony_ci 10987db96d56Sopenharmony_ci def test_coerce_id(self): 10997db96d56Sopenharmony_ci class Int(str): 11007db96d56Sopenharmony_ci def __index__(self): 11017db96d56Sopenharmony_ci return 10 11027db96d56Sopenharmony_ci 11037db96d56Sopenharmony_ci cid = interpreters._channel_id(Int(), force=True) 11047db96d56Sopenharmony_ci self.assertEqual(int(cid), 10) 11057db96d56Sopenharmony_ci 11067db96d56Sopenharmony_ci def test_bad_id(self): 11077db96d56Sopenharmony_ci self.assertRaises(TypeError, interpreters._channel_id, object()) 11087db96d56Sopenharmony_ci self.assertRaises(TypeError, interpreters._channel_id, 10.0) 11097db96d56Sopenharmony_ci self.assertRaises(TypeError, interpreters._channel_id, '10') 11107db96d56Sopenharmony_ci self.assertRaises(TypeError, interpreters._channel_id, b'10') 11117db96d56Sopenharmony_ci self.assertRaises(ValueError, interpreters._channel_id, -1) 11127db96d56Sopenharmony_ci self.assertRaises(OverflowError, interpreters._channel_id, 2**64) 11137db96d56Sopenharmony_ci 11147db96d56Sopenharmony_ci def test_bad_kwargs(self): 11157db96d56Sopenharmony_ci with self.assertRaises(ValueError): 11167db96d56Sopenharmony_ci interpreters._channel_id(10, send=False, recv=False) 11177db96d56Sopenharmony_ci 11187db96d56Sopenharmony_ci def test_does_not_exist(self): 11197db96d56Sopenharmony_ci cid = interpreters.channel_create() 11207db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelNotFoundError): 11217db96d56Sopenharmony_ci interpreters._channel_id(int(cid) + 1) # unforced 11227db96d56Sopenharmony_ci 11237db96d56Sopenharmony_ci def test_str(self): 11247db96d56Sopenharmony_ci cid = interpreters._channel_id(10, force=True) 11257db96d56Sopenharmony_ci self.assertEqual(str(cid), '10') 11267db96d56Sopenharmony_ci 11277db96d56Sopenharmony_ci def test_repr(self): 11287db96d56Sopenharmony_ci cid = interpreters._channel_id(10, force=True) 11297db96d56Sopenharmony_ci self.assertEqual(repr(cid), 'ChannelID(10)') 11307db96d56Sopenharmony_ci 11317db96d56Sopenharmony_ci cid = interpreters._channel_id(10, send=True, force=True) 11327db96d56Sopenharmony_ci self.assertEqual(repr(cid), 'ChannelID(10, send=True)') 11337db96d56Sopenharmony_ci 11347db96d56Sopenharmony_ci cid = interpreters._channel_id(10, recv=True, force=True) 11357db96d56Sopenharmony_ci self.assertEqual(repr(cid), 'ChannelID(10, recv=True)') 11367db96d56Sopenharmony_ci 11377db96d56Sopenharmony_ci cid = interpreters._channel_id(10, send=True, recv=True, force=True) 11387db96d56Sopenharmony_ci self.assertEqual(repr(cid), 'ChannelID(10)') 11397db96d56Sopenharmony_ci 11407db96d56Sopenharmony_ci def test_equality(self): 11417db96d56Sopenharmony_ci cid1 = interpreters.channel_create() 11427db96d56Sopenharmony_ci cid2 = interpreters._channel_id(int(cid1)) 11437db96d56Sopenharmony_ci cid3 = interpreters.channel_create() 11447db96d56Sopenharmony_ci 11457db96d56Sopenharmony_ci self.assertTrue(cid1 == cid1) 11467db96d56Sopenharmony_ci self.assertTrue(cid1 == cid2) 11477db96d56Sopenharmony_ci self.assertTrue(cid1 == int(cid1)) 11487db96d56Sopenharmony_ci self.assertTrue(int(cid1) == cid1) 11497db96d56Sopenharmony_ci self.assertTrue(cid1 == float(int(cid1))) 11507db96d56Sopenharmony_ci self.assertTrue(float(int(cid1)) == cid1) 11517db96d56Sopenharmony_ci self.assertFalse(cid1 == float(int(cid1)) + 0.1) 11527db96d56Sopenharmony_ci self.assertFalse(cid1 == str(int(cid1))) 11537db96d56Sopenharmony_ci self.assertFalse(cid1 == 2**1000) 11547db96d56Sopenharmony_ci self.assertFalse(cid1 == float('inf')) 11557db96d56Sopenharmony_ci self.assertFalse(cid1 == 'spam') 11567db96d56Sopenharmony_ci self.assertFalse(cid1 == cid3) 11577db96d56Sopenharmony_ci 11587db96d56Sopenharmony_ci self.assertFalse(cid1 != cid1) 11597db96d56Sopenharmony_ci self.assertFalse(cid1 != cid2) 11607db96d56Sopenharmony_ci self.assertTrue(cid1 != cid3) 11617db96d56Sopenharmony_ci 11627db96d56Sopenharmony_ci 11637db96d56Sopenharmony_ciclass ChannelTests(TestBase): 11647db96d56Sopenharmony_ci 11657db96d56Sopenharmony_ci def test_create_cid(self): 11667db96d56Sopenharmony_ci cid = interpreters.channel_create() 11677db96d56Sopenharmony_ci self.assertIsInstance(cid, interpreters.ChannelID) 11687db96d56Sopenharmony_ci 11697db96d56Sopenharmony_ci def test_sequential_ids(self): 11707db96d56Sopenharmony_ci before = interpreters.channel_list_all() 11717db96d56Sopenharmony_ci id1 = interpreters.channel_create() 11727db96d56Sopenharmony_ci id2 = interpreters.channel_create() 11737db96d56Sopenharmony_ci id3 = interpreters.channel_create() 11747db96d56Sopenharmony_ci after = interpreters.channel_list_all() 11757db96d56Sopenharmony_ci 11767db96d56Sopenharmony_ci self.assertEqual(id2, int(id1) + 1) 11777db96d56Sopenharmony_ci self.assertEqual(id3, int(id2) + 1) 11787db96d56Sopenharmony_ci self.assertEqual(set(after) - set(before), {id1, id2, id3}) 11797db96d56Sopenharmony_ci 11807db96d56Sopenharmony_ci def test_ids_global(self): 11817db96d56Sopenharmony_ci id1 = interpreters.create() 11827db96d56Sopenharmony_ci out = _run_output(id1, dedent(""" 11837db96d56Sopenharmony_ci import _xxsubinterpreters as _interpreters 11847db96d56Sopenharmony_ci cid = _interpreters.channel_create() 11857db96d56Sopenharmony_ci print(cid) 11867db96d56Sopenharmony_ci """)) 11877db96d56Sopenharmony_ci cid1 = int(out.strip()) 11887db96d56Sopenharmony_ci 11897db96d56Sopenharmony_ci id2 = interpreters.create() 11907db96d56Sopenharmony_ci out = _run_output(id2, dedent(""" 11917db96d56Sopenharmony_ci import _xxsubinterpreters as _interpreters 11927db96d56Sopenharmony_ci cid = _interpreters.channel_create() 11937db96d56Sopenharmony_ci print(cid) 11947db96d56Sopenharmony_ci """)) 11957db96d56Sopenharmony_ci cid2 = int(out.strip()) 11967db96d56Sopenharmony_ci 11977db96d56Sopenharmony_ci self.assertEqual(cid2, int(cid1) + 1) 11987db96d56Sopenharmony_ci 11997db96d56Sopenharmony_ci def test_channel_list_interpreters_none(self): 12007db96d56Sopenharmony_ci """Test listing interpreters for a channel with no associations.""" 12017db96d56Sopenharmony_ci # Test for channel with no associated interpreters. 12027db96d56Sopenharmony_ci cid = interpreters.channel_create() 12037db96d56Sopenharmony_ci send_interps = interpreters.channel_list_interpreters(cid, send=True) 12047db96d56Sopenharmony_ci recv_interps = interpreters.channel_list_interpreters(cid, send=False) 12057db96d56Sopenharmony_ci self.assertEqual(send_interps, []) 12067db96d56Sopenharmony_ci self.assertEqual(recv_interps, []) 12077db96d56Sopenharmony_ci 12087db96d56Sopenharmony_ci def test_channel_list_interpreters_basic(self): 12097db96d56Sopenharmony_ci """Test basic listing channel interpreters.""" 12107db96d56Sopenharmony_ci interp0 = interpreters.get_main() 12117db96d56Sopenharmony_ci cid = interpreters.channel_create() 12127db96d56Sopenharmony_ci interpreters.channel_send(cid, "send") 12137db96d56Sopenharmony_ci # Test for a channel that has one end associated to an interpreter. 12147db96d56Sopenharmony_ci send_interps = interpreters.channel_list_interpreters(cid, send=True) 12157db96d56Sopenharmony_ci recv_interps = interpreters.channel_list_interpreters(cid, send=False) 12167db96d56Sopenharmony_ci self.assertEqual(send_interps, [interp0]) 12177db96d56Sopenharmony_ci self.assertEqual(recv_interps, []) 12187db96d56Sopenharmony_ci 12197db96d56Sopenharmony_ci interp1 = interpreters.create() 12207db96d56Sopenharmony_ci _run_output(interp1, dedent(f""" 12217db96d56Sopenharmony_ci import _xxsubinterpreters as _interpreters 12227db96d56Sopenharmony_ci obj = _interpreters.channel_recv({cid}) 12237db96d56Sopenharmony_ci """)) 12247db96d56Sopenharmony_ci # Test for channel that has both ends associated to an interpreter. 12257db96d56Sopenharmony_ci send_interps = interpreters.channel_list_interpreters(cid, send=True) 12267db96d56Sopenharmony_ci recv_interps = interpreters.channel_list_interpreters(cid, send=False) 12277db96d56Sopenharmony_ci self.assertEqual(send_interps, [interp0]) 12287db96d56Sopenharmony_ci self.assertEqual(recv_interps, [interp1]) 12297db96d56Sopenharmony_ci 12307db96d56Sopenharmony_ci def test_channel_list_interpreters_multiple(self): 12317db96d56Sopenharmony_ci """Test listing interpreters for a channel with many associations.""" 12327db96d56Sopenharmony_ci interp0 = interpreters.get_main() 12337db96d56Sopenharmony_ci interp1 = interpreters.create() 12347db96d56Sopenharmony_ci interp2 = interpreters.create() 12357db96d56Sopenharmony_ci interp3 = interpreters.create() 12367db96d56Sopenharmony_ci cid = interpreters.channel_create() 12377db96d56Sopenharmony_ci 12387db96d56Sopenharmony_ci interpreters.channel_send(cid, "send") 12397db96d56Sopenharmony_ci _run_output(interp1, dedent(f""" 12407db96d56Sopenharmony_ci import _xxsubinterpreters as _interpreters 12417db96d56Sopenharmony_ci _interpreters.channel_send({cid}, "send") 12427db96d56Sopenharmony_ci """)) 12437db96d56Sopenharmony_ci _run_output(interp2, dedent(f""" 12447db96d56Sopenharmony_ci import _xxsubinterpreters as _interpreters 12457db96d56Sopenharmony_ci obj = _interpreters.channel_recv({cid}) 12467db96d56Sopenharmony_ci """)) 12477db96d56Sopenharmony_ci _run_output(interp3, dedent(f""" 12487db96d56Sopenharmony_ci import _xxsubinterpreters as _interpreters 12497db96d56Sopenharmony_ci obj = _interpreters.channel_recv({cid}) 12507db96d56Sopenharmony_ci """)) 12517db96d56Sopenharmony_ci send_interps = interpreters.channel_list_interpreters(cid, send=True) 12527db96d56Sopenharmony_ci recv_interps = interpreters.channel_list_interpreters(cid, send=False) 12537db96d56Sopenharmony_ci self.assertEqual(set(send_interps), {interp0, interp1}) 12547db96d56Sopenharmony_ci self.assertEqual(set(recv_interps), {interp2, interp3}) 12557db96d56Sopenharmony_ci 12567db96d56Sopenharmony_ci def test_channel_list_interpreters_destroyed(self): 12577db96d56Sopenharmony_ci """Test listing channel interpreters with a destroyed interpreter.""" 12587db96d56Sopenharmony_ci interp0 = interpreters.get_main() 12597db96d56Sopenharmony_ci interp1 = interpreters.create() 12607db96d56Sopenharmony_ci cid = interpreters.channel_create() 12617db96d56Sopenharmony_ci interpreters.channel_send(cid, "send") 12627db96d56Sopenharmony_ci _run_output(interp1, dedent(f""" 12637db96d56Sopenharmony_ci import _xxsubinterpreters as _interpreters 12647db96d56Sopenharmony_ci obj = _interpreters.channel_recv({cid}) 12657db96d56Sopenharmony_ci """)) 12667db96d56Sopenharmony_ci # Should be one interpreter associated with each end. 12677db96d56Sopenharmony_ci send_interps = interpreters.channel_list_interpreters(cid, send=True) 12687db96d56Sopenharmony_ci recv_interps = interpreters.channel_list_interpreters(cid, send=False) 12697db96d56Sopenharmony_ci self.assertEqual(send_interps, [interp0]) 12707db96d56Sopenharmony_ci self.assertEqual(recv_interps, [interp1]) 12717db96d56Sopenharmony_ci 12727db96d56Sopenharmony_ci interpreters.destroy(interp1) 12737db96d56Sopenharmony_ci # Destroyed interpreter should not be listed. 12747db96d56Sopenharmony_ci send_interps = interpreters.channel_list_interpreters(cid, send=True) 12757db96d56Sopenharmony_ci recv_interps = interpreters.channel_list_interpreters(cid, send=False) 12767db96d56Sopenharmony_ci self.assertEqual(send_interps, [interp0]) 12777db96d56Sopenharmony_ci self.assertEqual(recv_interps, []) 12787db96d56Sopenharmony_ci 12797db96d56Sopenharmony_ci def test_channel_list_interpreters_released(self): 12807db96d56Sopenharmony_ci """Test listing channel interpreters with a released channel.""" 12817db96d56Sopenharmony_ci # Set up one channel with main interpreter on the send end and two 12827db96d56Sopenharmony_ci # subinterpreters on the receive end. 12837db96d56Sopenharmony_ci interp0 = interpreters.get_main() 12847db96d56Sopenharmony_ci interp1 = interpreters.create() 12857db96d56Sopenharmony_ci interp2 = interpreters.create() 12867db96d56Sopenharmony_ci cid = interpreters.channel_create() 12877db96d56Sopenharmony_ci interpreters.channel_send(cid, "data") 12887db96d56Sopenharmony_ci _run_output(interp1, dedent(f""" 12897db96d56Sopenharmony_ci import _xxsubinterpreters as _interpreters 12907db96d56Sopenharmony_ci obj = _interpreters.channel_recv({cid}) 12917db96d56Sopenharmony_ci """)) 12927db96d56Sopenharmony_ci interpreters.channel_send(cid, "data") 12937db96d56Sopenharmony_ci _run_output(interp2, dedent(f""" 12947db96d56Sopenharmony_ci import _xxsubinterpreters as _interpreters 12957db96d56Sopenharmony_ci obj = _interpreters.channel_recv({cid}) 12967db96d56Sopenharmony_ci """)) 12977db96d56Sopenharmony_ci # Check the setup. 12987db96d56Sopenharmony_ci send_interps = interpreters.channel_list_interpreters(cid, send=True) 12997db96d56Sopenharmony_ci recv_interps = interpreters.channel_list_interpreters(cid, send=False) 13007db96d56Sopenharmony_ci self.assertEqual(len(send_interps), 1) 13017db96d56Sopenharmony_ci self.assertEqual(len(recv_interps), 2) 13027db96d56Sopenharmony_ci 13037db96d56Sopenharmony_ci # Release the main interpreter from the send end. 13047db96d56Sopenharmony_ci interpreters.channel_release(cid, send=True) 13057db96d56Sopenharmony_ci # Send end should have no associated interpreters. 13067db96d56Sopenharmony_ci send_interps = interpreters.channel_list_interpreters(cid, send=True) 13077db96d56Sopenharmony_ci recv_interps = interpreters.channel_list_interpreters(cid, send=False) 13087db96d56Sopenharmony_ci self.assertEqual(len(send_interps), 0) 13097db96d56Sopenharmony_ci self.assertEqual(len(recv_interps), 2) 13107db96d56Sopenharmony_ci 13117db96d56Sopenharmony_ci # Release one of the subinterpreters from the receive end. 13127db96d56Sopenharmony_ci _run_output(interp2, dedent(f""" 13137db96d56Sopenharmony_ci import _xxsubinterpreters as _interpreters 13147db96d56Sopenharmony_ci _interpreters.channel_release({cid}) 13157db96d56Sopenharmony_ci """)) 13167db96d56Sopenharmony_ci # Receive end should have the released interpreter removed. 13177db96d56Sopenharmony_ci send_interps = interpreters.channel_list_interpreters(cid, send=True) 13187db96d56Sopenharmony_ci recv_interps = interpreters.channel_list_interpreters(cid, send=False) 13197db96d56Sopenharmony_ci self.assertEqual(len(send_interps), 0) 13207db96d56Sopenharmony_ci self.assertEqual(recv_interps, [interp1]) 13217db96d56Sopenharmony_ci 13227db96d56Sopenharmony_ci def test_channel_list_interpreters_closed(self): 13237db96d56Sopenharmony_ci """Test listing channel interpreters with a closed channel.""" 13247db96d56Sopenharmony_ci interp0 = interpreters.get_main() 13257db96d56Sopenharmony_ci interp1 = interpreters.create() 13267db96d56Sopenharmony_ci cid = interpreters.channel_create() 13277db96d56Sopenharmony_ci # Put something in the channel so that it's not empty. 13287db96d56Sopenharmony_ci interpreters.channel_send(cid, "send") 13297db96d56Sopenharmony_ci 13307db96d56Sopenharmony_ci # Check initial state. 13317db96d56Sopenharmony_ci send_interps = interpreters.channel_list_interpreters(cid, send=True) 13327db96d56Sopenharmony_ci recv_interps = interpreters.channel_list_interpreters(cid, send=False) 13337db96d56Sopenharmony_ci self.assertEqual(len(send_interps), 1) 13347db96d56Sopenharmony_ci self.assertEqual(len(recv_interps), 0) 13357db96d56Sopenharmony_ci 13367db96d56Sopenharmony_ci # Force close the channel. 13377db96d56Sopenharmony_ci interpreters.channel_close(cid, force=True) 13387db96d56Sopenharmony_ci # Both ends should raise an error. 13397db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 13407db96d56Sopenharmony_ci interpreters.channel_list_interpreters(cid, send=True) 13417db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 13427db96d56Sopenharmony_ci interpreters.channel_list_interpreters(cid, send=False) 13437db96d56Sopenharmony_ci 13447db96d56Sopenharmony_ci def test_channel_list_interpreters_closed_send_end(self): 13457db96d56Sopenharmony_ci """Test listing channel interpreters with a channel's send end closed.""" 13467db96d56Sopenharmony_ci interp0 = interpreters.get_main() 13477db96d56Sopenharmony_ci interp1 = interpreters.create() 13487db96d56Sopenharmony_ci cid = interpreters.channel_create() 13497db96d56Sopenharmony_ci # Put something in the channel so that it's not empty. 13507db96d56Sopenharmony_ci interpreters.channel_send(cid, "send") 13517db96d56Sopenharmony_ci 13527db96d56Sopenharmony_ci # Check initial state. 13537db96d56Sopenharmony_ci send_interps = interpreters.channel_list_interpreters(cid, send=True) 13547db96d56Sopenharmony_ci recv_interps = interpreters.channel_list_interpreters(cid, send=False) 13557db96d56Sopenharmony_ci self.assertEqual(len(send_interps), 1) 13567db96d56Sopenharmony_ci self.assertEqual(len(recv_interps), 0) 13577db96d56Sopenharmony_ci 13587db96d56Sopenharmony_ci # Close the send end of the channel. 13597db96d56Sopenharmony_ci interpreters.channel_close(cid, send=True) 13607db96d56Sopenharmony_ci # Send end should raise an error. 13617db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 13627db96d56Sopenharmony_ci interpreters.channel_list_interpreters(cid, send=True) 13637db96d56Sopenharmony_ci # Receive end should not be closed (since channel is not empty). 13647db96d56Sopenharmony_ci recv_interps = interpreters.channel_list_interpreters(cid, send=False) 13657db96d56Sopenharmony_ci self.assertEqual(len(recv_interps), 0) 13667db96d56Sopenharmony_ci 13677db96d56Sopenharmony_ci # Close the receive end of the channel from a subinterpreter. 13687db96d56Sopenharmony_ci _run_output(interp1, dedent(f""" 13697db96d56Sopenharmony_ci import _xxsubinterpreters as _interpreters 13707db96d56Sopenharmony_ci _interpreters.channel_close({cid}, force=True) 13717db96d56Sopenharmony_ci """)) 13727db96d56Sopenharmony_ci # Both ends should raise an error. 13737db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 13747db96d56Sopenharmony_ci interpreters.channel_list_interpreters(cid, send=True) 13757db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 13767db96d56Sopenharmony_ci interpreters.channel_list_interpreters(cid, send=False) 13777db96d56Sopenharmony_ci 13787db96d56Sopenharmony_ci #################### 13797db96d56Sopenharmony_ci 13807db96d56Sopenharmony_ci def test_send_recv_main(self): 13817db96d56Sopenharmony_ci cid = interpreters.channel_create() 13827db96d56Sopenharmony_ci orig = b'spam' 13837db96d56Sopenharmony_ci interpreters.channel_send(cid, orig) 13847db96d56Sopenharmony_ci obj = interpreters.channel_recv(cid) 13857db96d56Sopenharmony_ci 13867db96d56Sopenharmony_ci self.assertEqual(obj, orig) 13877db96d56Sopenharmony_ci self.assertIsNot(obj, orig) 13887db96d56Sopenharmony_ci 13897db96d56Sopenharmony_ci def test_send_recv_same_interpreter(self): 13907db96d56Sopenharmony_ci id1 = interpreters.create() 13917db96d56Sopenharmony_ci out = _run_output(id1, dedent(""" 13927db96d56Sopenharmony_ci import _xxsubinterpreters as _interpreters 13937db96d56Sopenharmony_ci cid = _interpreters.channel_create() 13947db96d56Sopenharmony_ci orig = b'spam' 13957db96d56Sopenharmony_ci _interpreters.channel_send(cid, orig) 13967db96d56Sopenharmony_ci obj = _interpreters.channel_recv(cid) 13977db96d56Sopenharmony_ci assert obj is not orig 13987db96d56Sopenharmony_ci assert obj == orig 13997db96d56Sopenharmony_ci """)) 14007db96d56Sopenharmony_ci 14017db96d56Sopenharmony_ci def test_send_recv_different_interpreters(self): 14027db96d56Sopenharmony_ci cid = interpreters.channel_create() 14037db96d56Sopenharmony_ci id1 = interpreters.create() 14047db96d56Sopenharmony_ci out = _run_output(id1, dedent(f""" 14057db96d56Sopenharmony_ci import _xxsubinterpreters as _interpreters 14067db96d56Sopenharmony_ci _interpreters.channel_send({cid}, b'spam') 14077db96d56Sopenharmony_ci """)) 14087db96d56Sopenharmony_ci obj = interpreters.channel_recv(cid) 14097db96d56Sopenharmony_ci 14107db96d56Sopenharmony_ci self.assertEqual(obj, b'spam') 14117db96d56Sopenharmony_ci 14127db96d56Sopenharmony_ci def test_send_recv_different_threads(self): 14137db96d56Sopenharmony_ci cid = interpreters.channel_create() 14147db96d56Sopenharmony_ci 14157db96d56Sopenharmony_ci def f(): 14167db96d56Sopenharmony_ci while True: 14177db96d56Sopenharmony_ci try: 14187db96d56Sopenharmony_ci obj = interpreters.channel_recv(cid) 14197db96d56Sopenharmony_ci break 14207db96d56Sopenharmony_ci except interpreters.ChannelEmptyError: 14217db96d56Sopenharmony_ci time.sleep(0.1) 14227db96d56Sopenharmony_ci interpreters.channel_send(cid, obj) 14237db96d56Sopenharmony_ci t = threading.Thread(target=f) 14247db96d56Sopenharmony_ci t.start() 14257db96d56Sopenharmony_ci 14267db96d56Sopenharmony_ci interpreters.channel_send(cid, b'spam') 14277db96d56Sopenharmony_ci t.join() 14287db96d56Sopenharmony_ci obj = interpreters.channel_recv(cid) 14297db96d56Sopenharmony_ci 14307db96d56Sopenharmony_ci self.assertEqual(obj, b'spam') 14317db96d56Sopenharmony_ci 14327db96d56Sopenharmony_ci def test_send_recv_different_interpreters_and_threads(self): 14337db96d56Sopenharmony_ci cid = interpreters.channel_create() 14347db96d56Sopenharmony_ci id1 = interpreters.create() 14357db96d56Sopenharmony_ci out = None 14367db96d56Sopenharmony_ci 14377db96d56Sopenharmony_ci def f(): 14387db96d56Sopenharmony_ci nonlocal out 14397db96d56Sopenharmony_ci out = _run_output(id1, dedent(f""" 14407db96d56Sopenharmony_ci import time 14417db96d56Sopenharmony_ci import _xxsubinterpreters as _interpreters 14427db96d56Sopenharmony_ci while True: 14437db96d56Sopenharmony_ci try: 14447db96d56Sopenharmony_ci obj = _interpreters.channel_recv({cid}) 14457db96d56Sopenharmony_ci break 14467db96d56Sopenharmony_ci except _interpreters.ChannelEmptyError: 14477db96d56Sopenharmony_ci time.sleep(0.1) 14487db96d56Sopenharmony_ci assert(obj == b'spam') 14497db96d56Sopenharmony_ci _interpreters.channel_send({cid}, b'eggs') 14507db96d56Sopenharmony_ci """)) 14517db96d56Sopenharmony_ci t = threading.Thread(target=f) 14527db96d56Sopenharmony_ci t.start() 14537db96d56Sopenharmony_ci 14547db96d56Sopenharmony_ci interpreters.channel_send(cid, b'spam') 14557db96d56Sopenharmony_ci t.join() 14567db96d56Sopenharmony_ci obj = interpreters.channel_recv(cid) 14577db96d56Sopenharmony_ci 14587db96d56Sopenharmony_ci self.assertEqual(obj, b'eggs') 14597db96d56Sopenharmony_ci 14607db96d56Sopenharmony_ci def test_send_not_found(self): 14617db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelNotFoundError): 14627db96d56Sopenharmony_ci interpreters.channel_send(10, b'spam') 14637db96d56Sopenharmony_ci 14647db96d56Sopenharmony_ci def test_recv_not_found(self): 14657db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelNotFoundError): 14667db96d56Sopenharmony_ci interpreters.channel_recv(10) 14677db96d56Sopenharmony_ci 14687db96d56Sopenharmony_ci def test_recv_empty(self): 14697db96d56Sopenharmony_ci cid = interpreters.channel_create() 14707db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelEmptyError): 14717db96d56Sopenharmony_ci interpreters.channel_recv(cid) 14727db96d56Sopenharmony_ci 14737db96d56Sopenharmony_ci def test_recv_default(self): 14747db96d56Sopenharmony_ci default = object() 14757db96d56Sopenharmony_ci cid = interpreters.channel_create() 14767db96d56Sopenharmony_ci obj1 = interpreters.channel_recv(cid, default) 14777db96d56Sopenharmony_ci interpreters.channel_send(cid, None) 14787db96d56Sopenharmony_ci interpreters.channel_send(cid, 1) 14797db96d56Sopenharmony_ci interpreters.channel_send(cid, b'spam') 14807db96d56Sopenharmony_ci interpreters.channel_send(cid, b'eggs') 14817db96d56Sopenharmony_ci obj2 = interpreters.channel_recv(cid, default) 14827db96d56Sopenharmony_ci obj3 = interpreters.channel_recv(cid, default) 14837db96d56Sopenharmony_ci obj4 = interpreters.channel_recv(cid) 14847db96d56Sopenharmony_ci obj5 = interpreters.channel_recv(cid, default) 14857db96d56Sopenharmony_ci obj6 = interpreters.channel_recv(cid, default) 14867db96d56Sopenharmony_ci 14877db96d56Sopenharmony_ci self.assertIs(obj1, default) 14887db96d56Sopenharmony_ci self.assertIs(obj2, None) 14897db96d56Sopenharmony_ci self.assertEqual(obj3, 1) 14907db96d56Sopenharmony_ci self.assertEqual(obj4, b'spam') 14917db96d56Sopenharmony_ci self.assertEqual(obj5, b'eggs') 14927db96d56Sopenharmony_ci self.assertIs(obj6, default) 14937db96d56Sopenharmony_ci 14947db96d56Sopenharmony_ci def test_run_string_arg_unresolved(self): 14957db96d56Sopenharmony_ci cid = interpreters.channel_create() 14967db96d56Sopenharmony_ci interp = interpreters.create() 14977db96d56Sopenharmony_ci 14987db96d56Sopenharmony_ci out = _run_output(interp, dedent(""" 14997db96d56Sopenharmony_ci import _xxsubinterpreters as _interpreters 15007db96d56Sopenharmony_ci print(cid.end) 15017db96d56Sopenharmony_ci _interpreters.channel_send(cid, b'spam') 15027db96d56Sopenharmony_ci """), 15037db96d56Sopenharmony_ci dict(cid=cid.send)) 15047db96d56Sopenharmony_ci obj = interpreters.channel_recv(cid) 15057db96d56Sopenharmony_ci 15067db96d56Sopenharmony_ci self.assertEqual(obj, b'spam') 15077db96d56Sopenharmony_ci self.assertEqual(out.strip(), 'send') 15087db96d56Sopenharmony_ci 15097db96d56Sopenharmony_ci # XXX For now there is no high-level channel into which the 15107db96d56Sopenharmony_ci # sent channel ID can be converted... 15117db96d56Sopenharmony_ci # Note: this test caused crashes on some buildbots (bpo-33615). 15127db96d56Sopenharmony_ci @unittest.skip('disabled until high-level channels exist') 15137db96d56Sopenharmony_ci def test_run_string_arg_resolved(self): 15147db96d56Sopenharmony_ci cid = interpreters.channel_create() 15157db96d56Sopenharmony_ci cid = interpreters._channel_id(cid, _resolve=True) 15167db96d56Sopenharmony_ci interp = interpreters.create() 15177db96d56Sopenharmony_ci 15187db96d56Sopenharmony_ci out = _run_output(interp, dedent(""" 15197db96d56Sopenharmony_ci import _xxsubinterpreters as _interpreters 15207db96d56Sopenharmony_ci print(chan.id.end) 15217db96d56Sopenharmony_ci _interpreters.channel_send(chan.id, b'spam') 15227db96d56Sopenharmony_ci """), 15237db96d56Sopenharmony_ci dict(chan=cid.send)) 15247db96d56Sopenharmony_ci obj = interpreters.channel_recv(cid) 15257db96d56Sopenharmony_ci 15267db96d56Sopenharmony_ci self.assertEqual(obj, b'spam') 15277db96d56Sopenharmony_ci self.assertEqual(out.strip(), 'send') 15287db96d56Sopenharmony_ci 15297db96d56Sopenharmony_ci # close 15307db96d56Sopenharmony_ci 15317db96d56Sopenharmony_ci def test_close_single_user(self): 15327db96d56Sopenharmony_ci cid = interpreters.channel_create() 15337db96d56Sopenharmony_ci interpreters.channel_send(cid, b'spam') 15347db96d56Sopenharmony_ci interpreters.channel_recv(cid) 15357db96d56Sopenharmony_ci interpreters.channel_close(cid) 15367db96d56Sopenharmony_ci 15377db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 15387db96d56Sopenharmony_ci interpreters.channel_send(cid, b'eggs') 15397db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 15407db96d56Sopenharmony_ci interpreters.channel_recv(cid) 15417db96d56Sopenharmony_ci 15427db96d56Sopenharmony_ci def test_close_multiple_users(self): 15437db96d56Sopenharmony_ci cid = interpreters.channel_create() 15447db96d56Sopenharmony_ci id1 = interpreters.create() 15457db96d56Sopenharmony_ci id2 = interpreters.create() 15467db96d56Sopenharmony_ci interpreters.run_string(id1, dedent(f""" 15477db96d56Sopenharmony_ci import _xxsubinterpreters as _interpreters 15487db96d56Sopenharmony_ci _interpreters.channel_send({cid}, b'spam') 15497db96d56Sopenharmony_ci """)) 15507db96d56Sopenharmony_ci interpreters.run_string(id2, dedent(f""" 15517db96d56Sopenharmony_ci import _xxsubinterpreters as _interpreters 15527db96d56Sopenharmony_ci _interpreters.channel_recv({cid}) 15537db96d56Sopenharmony_ci """)) 15547db96d56Sopenharmony_ci interpreters.channel_close(cid) 15557db96d56Sopenharmony_ci with self.assertRaises(interpreters.RunFailedError) as cm: 15567db96d56Sopenharmony_ci interpreters.run_string(id1, dedent(f""" 15577db96d56Sopenharmony_ci _interpreters.channel_send({cid}, b'spam') 15587db96d56Sopenharmony_ci """)) 15597db96d56Sopenharmony_ci self.assertIn('ChannelClosedError', str(cm.exception)) 15607db96d56Sopenharmony_ci with self.assertRaises(interpreters.RunFailedError) as cm: 15617db96d56Sopenharmony_ci interpreters.run_string(id2, dedent(f""" 15627db96d56Sopenharmony_ci _interpreters.channel_send({cid}, b'spam') 15637db96d56Sopenharmony_ci """)) 15647db96d56Sopenharmony_ci self.assertIn('ChannelClosedError', str(cm.exception)) 15657db96d56Sopenharmony_ci 15667db96d56Sopenharmony_ci def test_close_multiple_times(self): 15677db96d56Sopenharmony_ci cid = interpreters.channel_create() 15687db96d56Sopenharmony_ci interpreters.channel_send(cid, b'spam') 15697db96d56Sopenharmony_ci interpreters.channel_recv(cid) 15707db96d56Sopenharmony_ci interpreters.channel_close(cid) 15717db96d56Sopenharmony_ci 15727db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 15737db96d56Sopenharmony_ci interpreters.channel_close(cid) 15747db96d56Sopenharmony_ci 15757db96d56Sopenharmony_ci def test_close_empty(self): 15767db96d56Sopenharmony_ci tests = [ 15777db96d56Sopenharmony_ci (False, False), 15787db96d56Sopenharmony_ci (True, False), 15797db96d56Sopenharmony_ci (False, True), 15807db96d56Sopenharmony_ci (True, True), 15817db96d56Sopenharmony_ci ] 15827db96d56Sopenharmony_ci for send, recv in tests: 15837db96d56Sopenharmony_ci with self.subTest((send, recv)): 15847db96d56Sopenharmony_ci cid = interpreters.channel_create() 15857db96d56Sopenharmony_ci interpreters.channel_send(cid, b'spam') 15867db96d56Sopenharmony_ci interpreters.channel_recv(cid) 15877db96d56Sopenharmony_ci interpreters.channel_close(cid, send=send, recv=recv) 15887db96d56Sopenharmony_ci 15897db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 15907db96d56Sopenharmony_ci interpreters.channel_send(cid, b'eggs') 15917db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 15927db96d56Sopenharmony_ci interpreters.channel_recv(cid) 15937db96d56Sopenharmony_ci 15947db96d56Sopenharmony_ci def test_close_defaults_with_unused_items(self): 15957db96d56Sopenharmony_ci cid = interpreters.channel_create() 15967db96d56Sopenharmony_ci interpreters.channel_send(cid, b'spam') 15977db96d56Sopenharmony_ci interpreters.channel_send(cid, b'ham') 15987db96d56Sopenharmony_ci 15997db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelNotEmptyError): 16007db96d56Sopenharmony_ci interpreters.channel_close(cid) 16017db96d56Sopenharmony_ci interpreters.channel_recv(cid) 16027db96d56Sopenharmony_ci interpreters.channel_send(cid, b'eggs') 16037db96d56Sopenharmony_ci 16047db96d56Sopenharmony_ci def test_close_recv_with_unused_items_unforced(self): 16057db96d56Sopenharmony_ci cid = interpreters.channel_create() 16067db96d56Sopenharmony_ci interpreters.channel_send(cid, b'spam') 16077db96d56Sopenharmony_ci interpreters.channel_send(cid, b'ham') 16087db96d56Sopenharmony_ci 16097db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelNotEmptyError): 16107db96d56Sopenharmony_ci interpreters.channel_close(cid, recv=True) 16117db96d56Sopenharmony_ci interpreters.channel_recv(cid) 16127db96d56Sopenharmony_ci interpreters.channel_send(cid, b'eggs') 16137db96d56Sopenharmony_ci interpreters.channel_recv(cid) 16147db96d56Sopenharmony_ci interpreters.channel_recv(cid) 16157db96d56Sopenharmony_ci interpreters.channel_close(cid, recv=True) 16167db96d56Sopenharmony_ci 16177db96d56Sopenharmony_ci def test_close_send_with_unused_items_unforced(self): 16187db96d56Sopenharmony_ci cid = interpreters.channel_create() 16197db96d56Sopenharmony_ci interpreters.channel_send(cid, b'spam') 16207db96d56Sopenharmony_ci interpreters.channel_send(cid, b'ham') 16217db96d56Sopenharmony_ci interpreters.channel_close(cid, send=True) 16227db96d56Sopenharmony_ci 16237db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 16247db96d56Sopenharmony_ci interpreters.channel_send(cid, b'eggs') 16257db96d56Sopenharmony_ci interpreters.channel_recv(cid) 16267db96d56Sopenharmony_ci interpreters.channel_recv(cid) 16277db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 16287db96d56Sopenharmony_ci interpreters.channel_recv(cid) 16297db96d56Sopenharmony_ci 16307db96d56Sopenharmony_ci def test_close_both_with_unused_items_unforced(self): 16317db96d56Sopenharmony_ci cid = interpreters.channel_create() 16327db96d56Sopenharmony_ci interpreters.channel_send(cid, b'spam') 16337db96d56Sopenharmony_ci interpreters.channel_send(cid, b'ham') 16347db96d56Sopenharmony_ci 16357db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelNotEmptyError): 16367db96d56Sopenharmony_ci interpreters.channel_close(cid, recv=True, send=True) 16377db96d56Sopenharmony_ci interpreters.channel_recv(cid) 16387db96d56Sopenharmony_ci interpreters.channel_send(cid, b'eggs') 16397db96d56Sopenharmony_ci interpreters.channel_recv(cid) 16407db96d56Sopenharmony_ci interpreters.channel_recv(cid) 16417db96d56Sopenharmony_ci interpreters.channel_close(cid, recv=True) 16427db96d56Sopenharmony_ci 16437db96d56Sopenharmony_ci def test_close_recv_with_unused_items_forced(self): 16447db96d56Sopenharmony_ci cid = interpreters.channel_create() 16457db96d56Sopenharmony_ci interpreters.channel_send(cid, b'spam') 16467db96d56Sopenharmony_ci interpreters.channel_send(cid, b'ham') 16477db96d56Sopenharmony_ci interpreters.channel_close(cid, recv=True, force=True) 16487db96d56Sopenharmony_ci 16497db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 16507db96d56Sopenharmony_ci interpreters.channel_send(cid, b'eggs') 16517db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 16527db96d56Sopenharmony_ci interpreters.channel_recv(cid) 16537db96d56Sopenharmony_ci 16547db96d56Sopenharmony_ci def test_close_send_with_unused_items_forced(self): 16557db96d56Sopenharmony_ci cid = interpreters.channel_create() 16567db96d56Sopenharmony_ci interpreters.channel_send(cid, b'spam') 16577db96d56Sopenharmony_ci interpreters.channel_send(cid, b'ham') 16587db96d56Sopenharmony_ci interpreters.channel_close(cid, send=True, force=True) 16597db96d56Sopenharmony_ci 16607db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 16617db96d56Sopenharmony_ci interpreters.channel_send(cid, b'eggs') 16627db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 16637db96d56Sopenharmony_ci interpreters.channel_recv(cid) 16647db96d56Sopenharmony_ci 16657db96d56Sopenharmony_ci def test_close_both_with_unused_items_forced(self): 16667db96d56Sopenharmony_ci cid = interpreters.channel_create() 16677db96d56Sopenharmony_ci interpreters.channel_send(cid, b'spam') 16687db96d56Sopenharmony_ci interpreters.channel_send(cid, b'ham') 16697db96d56Sopenharmony_ci interpreters.channel_close(cid, send=True, recv=True, force=True) 16707db96d56Sopenharmony_ci 16717db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 16727db96d56Sopenharmony_ci interpreters.channel_send(cid, b'eggs') 16737db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 16747db96d56Sopenharmony_ci interpreters.channel_recv(cid) 16757db96d56Sopenharmony_ci 16767db96d56Sopenharmony_ci def test_close_never_used(self): 16777db96d56Sopenharmony_ci cid = interpreters.channel_create() 16787db96d56Sopenharmony_ci interpreters.channel_close(cid) 16797db96d56Sopenharmony_ci 16807db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 16817db96d56Sopenharmony_ci interpreters.channel_send(cid, b'spam') 16827db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 16837db96d56Sopenharmony_ci interpreters.channel_recv(cid) 16847db96d56Sopenharmony_ci 16857db96d56Sopenharmony_ci def test_close_by_unassociated_interp(self): 16867db96d56Sopenharmony_ci cid = interpreters.channel_create() 16877db96d56Sopenharmony_ci interpreters.channel_send(cid, b'spam') 16887db96d56Sopenharmony_ci interp = interpreters.create() 16897db96d56Sopenharmony_ci interpreters.run_string(interp, dedent(f""" 16907db96d56Sopenharmony_ci import _xxsubinterpreters as _interpreters 16917db96d56Sopenharmony_ci _interpreters.channel_close({cid}, force=True) 16927db96d56Sopenharmony_ci """)) 16937db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 16947db96d56Sopenharmony_ci interpreters.channel_recv(cid) 16957db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 16967db96d56Sopenharmony_ci interpreters.channel_close(cid) 16977db96d56Sopenharmony_ci 16987db96d56Sopenharmony_ci def test_close_used_multiple_times_by_single_user(self): 16997db96d56Sopenharmony_ci cid = interpreters.channel_create() 17007db96d56Sopenharmony_ci interpreters.channel_send(cid, b'spam') 17017db96d56Sopenharmony_ci interpreters.channel_send(cid, b'spam') 17027db96d56Sopenharmony_ci interpreters.channel_send(cid, b'spam') 17037db96d56Sopenharmony_ci interpreters.channel_recv(cid) 17047db96d56Sopenharmony_ci interpreters.channel_close(cid, force=True) 17057db96d56Sopenharmony_ci 17067db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 17077db96d56Sopenharmony_ci interpreters.channel_send(cid, b'eggs') 17087db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 17097db96d56Sopenharmony_ci interpreters.channel_recv(cid) 17107db96d56Sopenharmony_ci 17117db96d56Sopenharmony_ci def test_channel_list_interpreters_invalid_channel(self): 17127db96d56Sopenharmony_ci cid = interpreters.channel_create() 17137db96d56Sopenharmony_ci # Test for invalid channel ID. 17147db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelNotFoundError): 17157db96d56Sopenharmony_ci interpreters.channel_list_interpreters(1000, send=True) 17167db96d56Sopenharmony_ci 17177db96d56Sopenharmony_ci interpreters.channel_close(cid) 17187db96d56Sopenharmony_ci # Test for a channel that has been closed. 17197db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 17207db96d56Sopenharmony_ci interpreters.channel_list_interpreters(cid, send=True) 17217db96d56Sopenharmony_ci 17227db96d56Sopenharmony_ci def test_channel_list_interpreters_invalid_args(self): 17237db96d56Sopenharmony_ci # Tests for invalid arguments passed to the API. 17247db96d56Sopenharmony_ci cid = interpreters.channel_create() 17257db96d56Sopenharmony_ci with self.assertRaises(TypeError): 17267db96d56Sopenharmony_ci interpreters.channel_list_interpreters(cid) 17277db96d56Sopenharmony_ci 17287db96d56Sopenharmony_ci 17297db96d56Sopenharmony_ciclass ChannelReleaseTests(TestBase): 17307db96d56Sopenharmony_ci 17317db96d56Sopenharmony_ci # XXX Add more test coverage a la the tests for close(). 17327db96d56Sopenharmony_ci 17337db96d56Sopenharmony_ci """ 17347db96d56Sopenharmony_ci - main / interp / other 17357db96d56Sopenharmony_ci - run in: current thread / new thread / other thread / different threads 17367db96d56Sopenharmony_ci - end / opposite 17377db96d56Sopenharmony_ci - force / no force 17387db96d56Sopenharmony_ci - used / not used (associated / not associated) 17397db96d56Sopenharmony_ci - empty / emptied / never emptied / partly emptied 17407db96d56Sopenharmony_ci - closed / not closed 17417db96d56Sopenharmony_ci - released / not released 17427db96d56Sopenharmony_ci - creator (interp) / other 17437db96d56Sopenharmony_ci - associated interpreter not running 17447db96d56Sopenharmony_ci - associated interpreter destroyed 17457db96d56Sopenharmony_ci """ 17467db96d56Sopenharmony_ci 17477db96d56Sopenharmony_ci """ 17487db96d56Sopenharmony_ci use 17497db96d56Sopenharmony_ci pre-release 17507db96d56Sopenharmony_ci release 17517db96d56Sopenharmony_ci after 17527db96d56Sopenharmony_ci check 17537db96d56Sopenharmony_ci """ 17547db96d56Sopenharmony_ci 17557db96d56Sopenharmony_ci """ 17567db96d56Sopenharmony_ci release in: main, interp1 17577db96d56Sopenharmony_ci creator: same, other (incl. interp2) 17587db96d56Sopenharmony_ci 17597db96d56Sopenharmony_ci use: None,send,recv,send/recv in None,same,other(incl. interp2),same+other(incl. interp2),all 17607db96d56Sopenharmony_ci pre-release: None,send,recv,both in None,same,other(incl. interp2),same+other(incl. interp2),all 17617db96d56Sopenharmony_ci pre-release forced: None,send,recv,both in None,same,other(incl. interp2),same+other(incl. interp2),all 17627db96d56Sopenharmony_ci 17637db96d56Sopenharmony_ci release: same 17647db96d56Sopenharmony_ci release forced: same 17657db96d56Sopenharmony_ci 17667db96d56Sopenharmony_ci use after: None,send,recv,send/recv in None,same,other(incl. interp2),same+other(incl. interp2),all 17677db96d56Sopenharmony_ci release after: None,send,recv,send/recv in None,same,other(incl. interp2),same+other(incl. interp2),all 17687db96d56Sopenharmony_ci check released: send/recv for same/other(incl. interp2) 17697db96d56Sopenharmony_ci check closed: send/recv for same/other(incl. interp2) 17707db96d56Sopenharmony_ci """ 17717db96d56Sopenharmony_ci 17727db96d56Sopenharmony_ci def test_single_user(self): 17737db96d56Sopenharmony_ci cid = interpreters.channel_create() 17747db96d56Sopenharmony_ci interpreters.channel_send(cid, b'spam') 17757db96d56Sopenharmony_ci interpreters.channel_recv(cid) 17767db96d56Sopenharmony_ci interpreters.channel_release(cid, send=True, recv=True) 17777db96d56Sopenharmony_ci 17787db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 17797db96d56Sopenharmony_ci interpreters.channel_send(cid, b'eggs') 17807db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 17817db96d56Sopenharmony_ci interpreters.channel_recv(cid) 17827db96d56Sopenharmony_ci 17837db96d56Sopenharmony_ci def test_multiple_users(self): 17847db96d56Sopenharmony_ci cid = interpreters.channel_create() 17857db96d56Sopenharmony_ci id1 = interpreters.create() 17867db96d56Sopenharmony_ci id2 = interpreters.create() 17877db96d56Sopenharmony_ci interpreters.run_string(id1, dedent(f""" 17887db96d56Sopenharmony_ci import _xxsubinterpreters as _interpreters 17897db96d56Sopenharmony_ci _interpreters.channel_send({cid}, b'spam') 17907db96d56Sopenharmony_ci """)) 17917db96d56Sopenharmony_ci out = _run_output(id2, dedent(f""" 17927db96d56Sopenharmony_ci import _xxsubinterpreters as _interpreters 17937db96d56Sopenharmony_ci obj = _interpreters.channel_recv({cid}) 17947db96d56Sopenharmony_ci _interpreters.channel_release({cid}) 17957db96d56Sopenharmony_ci print(repr(obj)) 17967db96d56Sopenharmony_ci """)) 17977db96d56Sopenharmony_ci interpreters.run_string(id1, dedent(f""" 17987db96d56Sopenharmony_ci _interpreters.channel_release({cid}) 17997db96d56Sopenharmony_ci """)) 18007db96d56Sopenharmony_ci 18017db96d56Sopenharmony_ci self.assertEqual(out.strip(), "b'spam'") 18027db96d56Sopenharmony_ci 18037db96d56Sopenharmony_ci def test_no_kwargs(self): 18047db96d56Sopenharmony_ci cid = interpreters.channel_create() 18057db96d56Sopenharmony_ci interpreters.channel_send(cid, b'spam') 18067db96d56Sopenharmony_ci interpreters.channel_recv(cid) 18077db96d56Sopenharmony_ci interpreters.channel_release(cid) 18087db96d56Sopenharmony_ci 18097db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 18107db96d56Sopenharmony_ci interpreters.channel_send(cid, b'eggs') 18117db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 18127db96d56Sopenharmony_ci interpreters.channel_recv(cid) 18137db96d56Sopenharmony_ci 18147db96d56Sopenharmony_ci def test_multiple_times(self): 18157db96d56Sopenharmony_ci cid = interpreters.channel_create() 18167db96d56Sopenharmony_ci interpreters.channel_send(cid, b'spam') 18177db96d56Sopenharmony_ci interpreters.channel_recv(cid) 18187db96d56Sopenharmony_ci interpreters.channel_release(cid, send=True, recv=True) 18197db96d56Sopenharmony_ci 18207db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 18217db96d56Sopenharmony_ci interpreters.channel_release(cid, send=True, recv=True) 18227db96d56Sopenharmony_ci 18237db96d56Sopenharmony_ci def test_with_unused_items(self): 18247db96d56Sopenharmony_ci cid = interpreters.channel_create() 18257db96d56Sopenharmony_ci interpreters.channel_send(cid, b'spam') 18267db96d56Sopenharmony_ci interpreters.channel_send(cid, b'ham') 18277db96d56Sopenharmony_ci interpreters.channel_release(cid, send=True, recv=True) 18287db96d56Sopenharmony_ci 18297db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 18307db96d56Sopenharmony_ci interpreters.channel_recv(cid) 18317db96d56Sopenharmony_ci 18327db96d56Sopenharmony_ci def test_never_used(self): 18337db96d56Sopenharmony_ci cid = interpreters.channel_create() 18347db96d56Sopenharmony_ci interpreters.channel_release(cid) 18357db96d56Sopenharmony_ci 18367db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 18377db96d56Sopenharmony_ci interpreters.channel_send(cid, b'spam') 18387db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 18397db96d56Sopenharmony_ci interpreters.channel_recv(cid) 18407db96d56Sopenharmony_ci 18417db96d56Sopenharmony_ci def test_by_unassociated_interp(self): 18427db96d56Sopenharmony_ci cid = interpreters.channel_create() 18437db96d56Sopenharmony_ci interpreters.channel_send(cid, b'spam') 18447db96d56Sopenharmony_ci interp = interpreters.create() 18457db96d56Sopenharmony_ci interpreters.run_string(interp, dedent(f""" 18467db96d56Sopenharmony_ci import _xxsubinterpreters as _interpreters 18477db96d56Sopenharmony_ci _interpreters.channel_release({cid}) 18487db96d56Sopenharmony_ci """)) 18497db96d56Sopenharmony_ci obj = interpreters.channel_recv(cid) 18507db96d56Sopenharmony_ci interpreters.channel_release(cid) 18517db96d56Sopenharmony_ci 18527db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 18537db96d56Sopenharmony_ci interpreters.channel_send(cid, b'eggs') 18547db96d56Sopenharmony_ci self.assertEqual(obj, b'spam') 18557db96d56Sopenharmony_ci 18567db96d56Sopenharmony_ci def test_close_if_unassociated(self): 18577db96d56Sopenharmony_ci # XXX Something's not right with this test... 18587db96d56Sopenharmony_ci cid = interpreters.channel_create() 18597db96d56Sopenharmony_ci interp = interpreters.create() 18607db96d56Sopenharmony_ci interpreters.run_string(interp, dedent(f""" 18617db96d56Sopenharmony_ci import _xxsubinterpreters as _interpreters 18627db96d56Sopenharmony_ci obj = _interpreters.channel_send({cid}, b'spam') 18637db96d56Sopenharmony_ci _interpreters.channel_release({cid}) 18647db96d56Sopenharmony_ci """)) 18657db96d56Sopenharmony_ci 18667db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 18677db96d56Sopenharmony_ci interpreters.channel_recv(cid) 18687db96d56Sopenharmony_ci 18697db96d56Sopenharmony_ci def test_partially(self): 18707db96d56Sopenharmony_ci # XXX Is partial close too weird/confusing? 18717db96d56Sopenharmony_ci cid = interpreters.channel_create() 18727db96d56Sopenharmony_ci interpreters.channel_send(cid, None) 18737db96d56Sopenharmony_ci interpreters.channel_recv(cid) 18747db96d56Sopenharmony_ci interpreters.channel_send(cid, b'spam') 18757db96d56Sopenharmony_ci interpreters.channel_release(cid, send=True) 18767db96d56Sopenharmony_ci obj = interpreters.channel_recv(cid) 18777db96d56Sopenharmony_ci 18787db96d56Sopenharmony_ci self.assertEqual(obj, b'spam') 18797db96d56Sopenharmony_ci 18807db96d56Sopenharmony_ci def test_used_multiple_times_by_single_user(self): 18817db96d56Sopenharmony_ci cid = interpreters.channel_create() 18827db96d56Sopenharmony_ci interpreters.channel_send(cid, b'spam') 18837db96d56Sopenharmony_ci interpreters.channel_send(cid, b'spam') 18847db96d56Sopenharmony_ci interpreters.channel_send(cid, b'spam') 18857db96d56Sopenharmony_ci interpreters.channel_recv(cid) 18867db96d56Sopenharmony_ci interpreters.channel_release(cid, send=True, recv=True) 18877db96d56Sopenharmony_ci 18887db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 18897db96d56Sopenharmony_ci interpreters.channel_send(cid, b'eggs') 18907db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 18917db96d56Sopenharmony_ci interpreters.channel_recv(cid) 18927db96d56Sopenharmony_ci 18937db96d56Sopenharmony_ci 18947db96d56Sopenharmony_ciclass ChannelCloseFixture(namedtuple('ChannelCloseFixture', 18957db96d56Sopenharmony_ci 'end interp other extra creator')): 18967db96d56Sopenharmony_ci 18977db96d56Sopenharmony_ci # Set this to True to avoid creating interpreters, e.g. when 18987db96d56Sopenharmony_ci # scanning through test permutations without running them. 18997db96d56Sopenharmony_ci QUICK = False 19007db96d56Sopenharmony_ci 19017db96d56Sopenharmony_ci def __new__(cls, end, interp, other, extra, creator): 19027db96d56Sopenharmony_ci assert end in ('send', 'recv') 19037db96d56Sopenharmony_ci if cls.QUICK: 19047db96d56Sopenharmony_ci known = {} 19057db96d56Sopenharmony_ci else: 19067db96d56Sopenharmony_ci interp = Interpreter.from_raw(interp) 19077db96d56Sopenharmony_ci other = Interpreter.from_raw(other) 19087db96d56Sopenharmony_ci extra = Interpreter.from_raw(extra) 19097db96d56Sopenharmony_ci known = { 19107db96d56Sopenharmony_ci interp.name: interp, 19117db96d56Sopenharmony_ci other.name: other, 19127db96d56Sopenharmony_ci extra.name: extra, 19137db96d56Sopenharmony_ci } 19147db96d56Sopenharmony_ci if not creator: 19157db96d56Sopenharmony_ci creator = 'same' 19167db96d56Sopenharmony_ci self = super().__new__(cls, end, interp, other, extra, creator) 19177db96d56Sopenharmony_ci self._prepped = set() 19187db96d56Sopenharmony_ci self._state = ChannelState() 19197db96d56Sopenharmony_ci self._known = known 19207db96d56Sopenharmony_ci return self 19217db96d56Sopenharmony_ci 19227db96d56Sopenharmony_ci @property 19237db96d56Sopenharmony_ci def state(self): 19247db96d56Sopenharmony_ci return self._state 19257db96d56Sopenharmony_ci 19267db96d56Sopenharmony_ci @property 19277db96d56Sopenharmony_ci def cid(self): 19287db96d56Sopenharmony_ci try: 19297db96d56Sopenharmony_ci return self._cid 19307db96d56Sopenharmony_ci except AttributeError: 19317db96d56Sopenharmony_ci creator = self._get_interpreter(self.creator) 19327db96d56Sopenharmony_ci self._cid = self._new_channel(creator) 19337db96d56Sopenharmony_ci return self._cid 19347db96d56Sopenharmony_ci 19357db96d56Sopenharmony_ci def get_interpreter(self, interp): 19367db96d56Sopenharmony_ci interp = self._get_interpreter(interp) 19377db96d56Sopenharmony_ci self._prep_interpreter(interp) 19387db96d56Sopenharmony_ci return interp 19397db96d56Sopenharmony_ci 19407db96d56Sopenharmony_ci def expect_closed_error(self, end=None): 19417db96d56Sopenharmony_ci if end is None: 19427db96d56Sopenharmony_ci end = self.end 19437db96d56Sopenharmony_ci if end == 'recv' and self.state.closed == 'send': 19447db96d56Sopenharmony_ci return False 19457db96d56Sopenharmony_ci return bool(self.state.closed) 19467db96d56Sopenharmony_ci 19477db96d56Sopenharmony_ci def prep_interpreter(self, interp): 19487db96d56Sopenharmony_ci self._prep_interpreter(interp) 19497db96d56Sopenharmony_ci 19507db96d56Sopenharmony_ci def record_action(self, action, result): 19517db96d56Sopenharmony_ci self._state = result 19527db96d56Sopenharmony_ci 19537db96d56Sopenharmony_ci def clean_up(self): 19547db96d56Sopenharmony_ci clean_up_interpreters() 19557db96d56Sopenharmony_ci clean_up_channels() 19567db96d56Sopenharmony_ci 19577db96d56Sopenharmony_ci # internal methods 19587db96d56Sopenharmony_ci 19597db96d56Sopenharmony_ci def _new_channel(self, creator): 19607db96d56Sopenharmony_ci if creator.name == 'main': 19617db96d56Sopenharmony_ci return interpreters.channel_create() 19627db96d56Sopenharmony_ci else: 19637db96d56Sopenharmony_ci ch = interpreters.channel_create() 19647db96d56Sopenharmony_ci run_interp(creator.id, f""" 19657db96d56Sopenharmony_ci import _xxsubinterpreters 19667db96d56Sopenharmony_ci cid = _xxsubinterpreters.channel_create() 19677db96d56Sopenharmony_ci # We purposefully send back an int to avoid tying the 19687db96d56Sopenharmony_ci # channel to the other interpreter. 19697db96d56Sopenharmony_ci _xxsubinterpreters.channel_send({ch}, int(cid)) 19707db96d56Sopenharmony_ci del _xxsubinterpreters 19717db96d56Sopenharmony_ci """) 19727db96d56Sopenharmony_ci self._cid = interpreters.channel_recv(ch) 19737db96d56Sopenharmony_ci return self._cid 19747db96d56Sopenharmony_ci 19757db96d56Sopenharmony_ci def _get_interpreter(self, interp): 19767db96d56Sopenharmony_ci if interp in ('same', 'interp'): 19777db96d56Sopenharmony_ci return self.interp 19787db96d56Sopenharmony_ci elif interp == 'other': 19797db96d56Sopenharmony_ci return self.other 19807db96d56Sopenharmony_ci elif interp == 'extra': 19817db96d56Sopenharmony_ci return self.extra 19827db96d56Sopenharmony_ci else: 19837db96d56Sopenharmony_ci name = interp 19847db96d56Sopenharmony_ci try: 19857db96d56Sopenharmony_ci interp = self._known[name] 19867db96d56Sopenharmony_ci except KeyError: 19877db96d56Sopenharmony_ci interp = self._known[name] = Interpreter(name) 19887db96d56Sopenharmony_ci return interp 19897db96d56Sopenharmony_ci 19907db96d56Sopenharmony_ci def _prep_interpreter(self, interp): 19917db96d56Sopenharmony_ci if interp.id in self._prepped: 19927db96d56Sopenharmony_ci return 19937db96d56Sopenharmony_ci self._prepped.add(interp.id) 19947db96d56Sopenharmony_ci if interp.name == 'main': 19957db96d56Sopenharmony_ci return 19967db96d56Sopenharmony_ci run_interp(interp.id, f""" 19977db96d56Sopenharmony_ci import _xxsubinterpreters as interpreters 19987db96d56Sopenharmony_ci import test.test__xxsubinterpreters as helpers 19997db96d56Sopenharmony_ci ChannelState = helpers.ChannelState 20007db96d56Sopenharmony_ci try: 20017db96d56Sopenharmony_ci cid 20027db96d56Sopenharmony_ci except NameError: 20037db96d56Sopenharmony_ci cid = interpreters._channel_id({self.cid}) 20047db96d56Sopenharmony_ci """) 20057db96d56Sopenharmony_ci 20067db96d56Sopenharmony_ci 20077db96d56Sopenharmony_ci@unittest.skip('these tests take several hours to run') 20087db96d56Sopenharmony_ciclass ExhaustiveChannelTests(TestBase): 20097db96d56Sopenharmony_ci 20107db96d56Sopenharmony_ci """ 20117db96d56Sopenharmony_ci - main / interp / other 20127db96d56Sopenharmony_ci - run in: current thread / new thread / other thread / different threads 20137db96d56Sopenharmony_ci - end / opposite 20147db96d56Sopenharmony_ci - force / no force 20157db96d56Sopenharmony_ci - used / not used (associated / not associated) 20167db96d56Sopenharmony_ci - empty / emptied / never emptied / partly emptied 20177db96d56Sopenharmony_ci - closed / not closed 20187db96d56Sopenharmony_ci - released / not released 20197db96d56Sopenharmony_ci - creator (interp) / other 20207db96d56Sopenharmony_ci - associated interpreter not running 20217db96d56Sopenharmony_ci - associated interpreter destroyed 20227db96d56Sopenharmony_ci 20237db96d56Sopenharmony_ci - close after unbound 20247db96d56Sopenharmony_ci """ 20257db96d56Sopenharmony_ci 20267db96d56Sopenharmony_ci """ 20277db96d56Sopenharmony_ci use 20287db96d56Sopenharmony_ci pre-close 20297db96d56Sopenharmony_ci close 20307db96d56Sopenharmony_ci after 20317db96d56Sopenharmony_ci check 20327db96d56Sopenharmony_ci """ 20337db96d56Sopenharmony_ci 20347db96d56Sopenharmony_ci """ 20357db96d56Sopenharmony_ci close in: main, interp1 20367db96d56Sopenharmony_ci creator: same, other, extra 20377db96d56Sopenharmony_ci 20387db96d56Sopenharmony_ci use: None,send,recv,send/recv in None,same,other,same+other,all 20397db96d56Sopenharmony_ci pre-close: None,send,recv in None,same,other,same+other,all 20407db96d56Sopenharmony_ci pre-close forced: None,send,recv in None,same,other,same+other,all 20417db96d56Sopenharmony_ci 20427db96d56Sopenharmony_ci close: same 20437db96d56Sopenharmony_ci close forced: same 20447db96d56Sopenharmony_ci 20457db96d56Sopenharmony_ci use after: None,send,recv,send/recv in None,same,other,extra,same+other,all 20467db96d56Sopenharmony_ci close after: None,send,recv,send/recv in None,same,other,extra,same+other,all 20477db96d56Sopenharmony_ci check closed: send/recv for same/other(incl. interp2) 20487db96d56Sopenharmony_ci """ 20497db96d56Sopenharmony_ci 20507db96d56Sopenharmony_ci def iter_action_sets(self): 20517db96d56Sopenharmony_ci # - used / not used (associated / not associated) 20527db96d56Sopenharmony_ci # - empty / emptied / never emptied / partly emptied 20537db96d56Sopenharmony_ci # - closed / not closed 20547db96d56Sopenharmony_ci # - released / not released 20557db96d56Sopenharmony_ci 20567db96d56Sopenharmony_ci # never used 20577db96d56Sopenharmony_ci yield [] 20587db96d56Sopenharmony_ci 20597db96d56Sopenharmony_ci # only pre-closed (and possible used after) 20607db96d56Sopenharmony_ci for closeactions in self._iter_close_action_sets('same', 'other'): 20617db96d56Sopenharmony_ci yield closeactions 20627db96d56Sopenharmony_ci for postactions in self._iter_post_close_action_sets(): 20637db96d56Sopenharmony_ci yield closeactions + postactions 20647db96d56Sopenharmony_ci for closeactions in self._iter_close_action_sets('other', 'extra'): 20657db96d56Sopenharmony_ci yield closeactions 20667db96d56Sopenharmony_ci for postactions in self._iter_post_close_action_sets(): 20677db96d56Sopenharmony_ci yield closeactions + postactions 20687db96d56Sopenharmony_ci 20697db96d56Sopenharmony_ci # used 20707db96d56Sopenharmony_ci for useactions in self._iter_use_action_sets('same', 'other'): 20717db96d56Sopenharmony_ci yield useactions 20727db96d56Sopenharmony_ci for closeactions in self._iter_close_action_sets('same', 'other'): 20737db96d56Sopenharmony_ci actions = useactions + closeactions 20747db96d56Sopenharmony_ci yield actions 20757db96d56Sopenharmony_ci for postactions in self._iter_post_close_action_sets(): 20767db96d56Sopenharmony_ci yield actions + postactions 20777db96d56Sopenharmony_ci for closeactions in self._iter_close_action_sets('other', 'extra'): 20787db96d56Sopenharmony_ci actions = useactions + closeactions 20797db96d56Sopenharmony_ci yield actions 20807db96d56Sopenharmony_ci for postactions in self._iter_post_close_action_sets(): 20817db96d56Sopenharmony_ci yield actions + postactions 20827db96d56Sopenharmony_ci for useactions in self._iter_use_action_sets('other', 'extra'): 20837db96d56Sopenharmony_ci yield useactions 20847db96d56Sopenharmony_ci for closeactions in self._iter_close_action_sets('same', 'other'): 20857db96d56Sopenharmony_ci actions = useactions + closeactions 20867db96d56Sopenharmony_ci yield actions 20877db96d56Sopenharmony_ci for postactions in self._iter_post_close_action_sets(): 20887db96d56Sopenharmony_ci yield actions + postactions 20897db96d56Sopenharmony_ci for closeactions in self._iter_close_action_sets('other', 'extra'): 20907db96d56Sopenharmony_ci actions = useactions + closeactions 20917db96d56Sopenharmony_ci yield actions 20927db96d56Sopenharmony_ci for postactions in self._iter_post_close_action_sets(): 20937db96d56Sopenharmony_ci yield actions + postactions 20947db96d56Sopenharmony_ci 20957db96d56Sopenharmony_ci def _iter_use_action_sets(self, interp1, interp2): 20967db96d56Sopenharmony_ci interps = (interp1, interp2) 20977db96d56Sopenharmony_ci 20987db96d56Sopenharmony_ci # only recv end used 20997db96d56Sopenharmony_ci yield [ 21007db96d56Sopenharmony_ci ChannelAction('use', 'recv', interp1), 21017db96d56Sopenharmony_ci ] 21027db96d56Sopenharmony_ci yield [ 21037db96d56Sopenharmony_ci ChannelAction('use', 'recv', interp2), 21047db96d56Sopenharmony_ci ] 21057db96d56Sopenharmony_ci yield [ 21067db96d56Sopenharmony_ci ChannelAction('use', 'recv', interp1), 21077db96d56Sopenharmony_ci ChannelAction('use', 'recv', interp2), 21087db96d56Sopenharmony_ci ] 21097db96d56Sopenharmony_ci 21107db96d56Sopenharmony_ci # never emptied 21117db96d56Sopenharmony_ci yield [ 21127db96d56Sopenharmony_ci ChannelAction('use', 'send', interp1), 21137db96d56Sopenharmony_ci ] 21147db96d56Sopenharmony_ci yield [ 21157db96d56Sopenharmony_ci ChannelAction('use', 'send', interp2), 21167db96d56Sopenharmony_ci ] 21177db96d56Sopenharmony_ci yield [ 21187db96d56Sopenharmony_ci ChannelAction('use', 'send', interp1), 21197db96d56Sopenharmony_ci ChannelAction('use', 'send', interp2), 21207db96d56Sopenharmony_ci ] 21217db96d56Sopenharmony_ci 21227db96d56Sopenharmony_ci # partially emptied 21237db96d56Sopenharmony_ci for interp1 in interps: 21247db96d56Sopenharmony_ci for interp2 in interps: 21257db96d56Sopenharmony_ci for interp3 in interps: 21267db96d56Sopenharmony_ci yield [ 21277db96d56Sopenharmony_ci ChannelAction('use', 'send', interp1), 21287db96d56Sopenharmony_ci ChannelAction('use', 'send', interp2), 21297db96d56Sopenharmony_ci ChannelAction('use', 'recv', interp3), 21307db96d56Sopenharmony_ci ] 21317db96d56Sopenharmony_ci 21327db96d56Sopenharmony_ci # fully emptied 21337db96d56Sopenharmony_ci for interp1 in interps: 21347db96d56Sopenharmony_ci for interp2 in interps: 21357db96d56Sopenharmony_ci for interp3 in interps: 21367db96d56Sopenharmony_ci for interp4 in interps: 21377db96d56Sopenharmony_ci yield [ 21387db96d56Sopenharmony_ci ChannelAction('use', 'send', interp1), 21397db96d56Sopenharmony_ci ChannelAction('use', 'send', interp2), 21407db96d56Sopenharmony_ci ChannelAction('use', 'recv', interp3), 21417db96d56Sopenharmony_ci ChannelAction('use', 'recv', interp4), 21427db96d56Sopenharmony_ci ] 21437db96d56Sopenharmony_ci 21447db96d56Sopenharmony_ci def _iter_close_action_sets(self, interp1, interp2): 21457db96d56Sopenharmony_ci ends = ('recv', 'send') 21467db96d56Sopenharmony_ci interps = (interp1, interp2) 21477db96d56Sopenharmony_ci for force in (True, False): 21487db96d56Sopenharmony_ci op = 'force-close' if force else 'close' 21497db96d56Sopenharmony_ci for interp in interps: 21507db96d56Sopenharmony_ci for end in ends: 21517db96d56Sopenharmony_ci yield [ 21527db96d56Sopenharmony_ci ChannelAction(op, end, interp), 21537db96d56Sopenharmony_ci ] 21547db96d56Sopenharmony_ci for recvop in ('close', 'force-close'): 21557db96d56Sopenharmony_ci for sendop in ('close', 'force-close'): 21567db96d56Sopenharmony_ci for recv in interps: 21577db96d56Sopenharmony_ci for send in interps: 21587db96d56Sopenharmony_ci yield [ 21597db96d56Sopenharmony_ci ChannelAction(recvop, 'recv', recv), 21607db96d56Sopenharmony_ci ChannelAction(sendop, 'send', send), 21617db96d56Sopenharmony_ci ] 21627db96d56Sopenharmony_ci 21637db96d56Sopenharmony_ci def _iter_post_close_action_sets(self): 21647db96d56Sopenharmony_ci for interp in ('same', 'extra', 'other'): 21657db96d56Sopenharmony_ci yield [ 21667db96d56Sopenharmony_ci ChannelAction('use', 'recv', interp), 21677db96d56Sopenharmony_ci ] 21687db96d56Sopenharmony_ci yield [ 21697db96d56Sopenharmony_ci ChannelAction('use', 'send', interp), 21707db96d56Sopenharmony_ci ] 21717db96d56Sopenharmony_ci 21727db96d56Sopenharmony_ci def run_actions(self, fix, actions): 21737db96d56Sopenharmony_ci for action in actions: 21747db96d56Sopenharmony_ci self.run_action(fix, action) 21757db96d56Sopenharmony_ci 21767db96d56Sopenharmony_ci def run_action(self, fix, action, *, hideclosed=True): 21777db96d56Sopenharmony_ci end = action.resolve_end(fix.end) 21787db96d56Sopenharmony_ci interp = action.resolve_interp(fix.interp, fix.other, fix.extra) 21797db96d56Sopenharmony_ci fix.prep_interpreter(interp) 21807db96d56Sopenharmony_ci if interp.name == 'main': 21817db96d56Sopenharmony_ci result = run_action( 21827db96d56Sopenharmony_ci fix.cid, 21837db96d56Sopenharmony_ci action.action, 21847db96d56Sopenharmony_ci end, 21857db96d56Sopenharmony_ci fix.state, 21867db96d56Sopenharmony_ci hideclosed=hideclosed, 21877db96d56Sopenharmony_ci ) 21887db96d56Sopenharmony_ci fix.record_action(action, result) 21897db96d56Sopenharmony_ci else: 21907db96d56Sopenharmony_ci _cid = interpreters.channel_create() 21917db96d56Sopenharmony_ci run_interp(interp.id, f""" 21927db96d56Sopenharmony_ci result = helpers.run_action( 21937db96d56Sopenharmony_ci {fix.cid}, 21947db96d56Sopenharmony_ci {repr(action.action)}, 21957db96d56Sopenharmony_ci {repr(end)}, 21967db96d56Sopenharmony_ci {repr(fix.state)}, 21977db96d56Sopenharmony_ci hideclosed={hideclosed}, 21987db96d56Sopenharmony_ci ) 21997db96d56Sopenharmony_ci interpreters.channel_send({_cid}, result.pending.to_bytes(1, 'little')) 22007db96d56Sopenharmony_ci interpreters.channel_send({_cid}, b'X' if result.closed else b'') 22017db96d56Sopenharmony_ci """) 22027db96d56Sopenharmony_ci result = ChannelState( 22037db96d56Sopenharmony_ci pending=int.from_bytes(interpreters.channel_recv(_cid), 'little'), 22047db96d56Sopenharmony_ci closed=bool(interpreters.channel_recv(_cid)), 22057db96d56Sopenharmony_ci ) 22067db96d56Sopenharmony_ci fix.record_action(action, result) 22077db96d56Sopenharmony_ci 22087db96d56Sopenharmony_ci def iter_fixtures(self): 22097db96d56Sopenharmony_ci # XXX threads? 22107db96d56Sopenharmony_ci interpreters = [ 22117db96d56Sopenharmony_ci ('main', 'interp', 'extra'), 22127db96d56Sopenharmony_ci ('interp', 'main', 'extra'), 22137db96d56Sopenharmony_ci ('interp1', 'interp2', 'extra'), 22147db96d56Sopenharmony_ci ('interp1', 'interp2', 'main'), 22157db96d56Sopenharmony_ci ] 22167db96d56Sopenharmony_ci for interp, other, extra in interpreters: 22177db96d56Sopenharmony_ci for creator in ('same', 'other', 'creator'): 22187db96d56Sopenharmony_ci for end in ('send', 'recv'): 22197db96d56Sopenharmony_ci yield ChannelCloseFixture(end, interp, other, extra, creator) 22207db96d56Sopenharmony_ci 22217db96d56Sopenharmony_ci def _close(self, fix, *, force): 22227db96d56Sopenharmony_ci op = 'force-close' if force else 'close' 22237db96d56Sopenharmony_ci close = ChannelAction(op, fix.end, 'same') 22247db96d56Sopenharmony_ci if not fix.expect_closed_error(): 22257db96d56Sopenharmony_ci self.run_action(fix, close, hideclosed=False) 22267db96d56Sopenharmony_ci else: 22277db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 22287db96d56Sopenharmony_ci self.run_action(fix, close, hideclosed=False) 22297db96d56Sopenharmony_ci 22307db96d56Sopenharmony_ci def _assert_closed_in_interp(self, fix, interp=None): 22317db96d56Sopenharmony_ci if interp is None or interp.name == 'main': 22327db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 22337db96d56Sopenharmony_ci interpreters.channel_recv(fix.cid) 22347db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 22357db96d56Sopenharmony_ci interpreters.channel_send(fix.cid, b'spam') 22367db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 22377db96d56Sopenharmony_ci interpreters.channel_close(fix.cid) 22387db96d56Sopenharmony_ci with self.assertRaises(interpreters.ChannelClosedError): 22397db96d56Sopenharmony_ci interpreters.channel_close(fix.cid, force=True) 22407db96d56Sopenharmony_ci else: 22417db96d56Sopenharmony_ci run_interp(interp.id, f""" 22427db96d56Sopenharmony_ci with helpers.expect_channel_closed(): 22437db96d56Sopenharmony_ci interpreters.channel_recv(cid) 22447db96d56Sopenharmony_ci """) 22457db96d56Sopenharmony_ci run_interp(interp.id, f""" 22467db96d56Sopenharmony_ci with helpers.expect_channel_closed(): 22477db96d56Sopenharmony_ci interpreters.channel_send(cid, b'spam') 22487db96d56Sopenharmony_ci """) 22497db96d56Sopenharmony_ci run_interp(interp.id, f""" 22507db96d56Sopenharmony_ci with helpers.expect_channel_closed(): 22517db96d56Sopenharmony_ci interpreters.channel_close(cid) 22527db96d56Sopenharmony_ci """) 22537db96d56Sopenharmony_ci run_interp(interp.id, f""" 22547db96d56Sopenharmony_ci with helpers.expect_channel_closed(): 22557db96d56Sopenharmony_ci interpreters.channel_close(cid, force=True) 22567db96d56Sopenharmony_ci """) 22577db96d56Sopenharmony_ci 22587db96d56Sopenharmony_ci def _assert_closed(self, fix): 22597db96d56Sopenharmony_ci self.assertTrue(fix.state.closed) 22607db96d56Sopenharmony_ci 22617db96d56Sopenharmony_ci for _ in range(fix.state.pending): 22627db96d56Sopenharmony_ci interpreters.channel_recv(fix.cid) 22637db96d56Sopenharmony_ci self._assert_closed_in_interp(fix) 22647db96d56Sopenharmony_ci 22657db96d56Sopenharmony_ci for interp in ('same', 'other'): 22667db96d56Sopenharmony_ci interp = fix.get_interpreter(interp) 22677db96d56Sopenharmony_ci if interp.name == 'main': 22687db96d56Sopenharmony_ci continue 22697db96d56Sopenharmony_ci self._assert_closed_in_interp(fix, interp) 22707db96d56Sopenharmony_ci 22717db96d56Sopenharmony_ci interp = fix.get_interpreter('fresh') 22727db96d56Sopenharmony_ci self._assert_closed_in_interp(fix, interp) 22737db96d56Sopenharmony_ci 22747db96d56Sopenharmony_ci def _iter_close_tests(self, verbose=False): 22757db96d56Sopenharmony_ci i = 0 22767db96d56Sopenharmony_ci for actions in self.iter_action_sets(): 22777db96d56Sopenharmony_ci print() 22787db96d56Sopenharmony_ci for fix in self.iter_fixtures(): 22797db96d56Sopenharmony_ci i += 1 22807db96d56Sopenharmony_ci if i > 1000: 22817db96d56Sopenharmony_ci return 22827db96d56Sopenharmony_ci if verbose: 22837db96d56Sopenharmony_ci if (i - 1) % 6 == 0: 22847db96d56Sopenharmony_ci print() 22857db96d56Sopenharmony_ci print(i, fix, '({} actions)'.format(len(actions))) 22867db96d56Sopenharmony_ci else: 22877db96d56Sopenharmony_ci if (i - 1) % 6 == 0: 22887db96d56Sopenharmony_ci print(' ', end='') 22897db96d56Sopenharmony_ci print('.', end=''); sys.stdout.flush() 22907db96d56Sopenharmony_ci yield i, fix, actions 22917db96d56Sopenharmony_ci if verbose: 22927db96d56Sopenharmony_ci print('---') 22937db96d56Sopenharmony_ci print() 22947db96d56Sopenharmony_ci 22957db96d56Sopenharmony_ci # This is useful for scanning through the possible tests. 22967db96d56Sopenharmony_ci def _skim_close_tests(self): 22977db96d56Sopenharmony_ci ChannelCloseFixture.QUICK = True 22987db96d56Sopenharmony_ci for i, fix, actions in self._iter_close_tests(): 22997db96d56Sopenharmony_ci pass 23007db96d56Sopenharmony_ci 23017db96d56Sopenharmony_ci def test_close(self): 23027db96d56Sopenharmony_ci for i, fix, actions in self._iter_close_tests(): 23037db96d56Sopenharmony_ci with self.subTest('{} {} {}'.format(i, fix, actions)): 23047db96d56Sopenharmony_ci fix.prep_interpreter(fix.interp) 23057db96d56Sopenharmony_ci self.run_actions(fix, actions) 23067db96d56Sopenharmony_ci 23077db96d56Sopenharmony_ci self._close(fix, force=False) 23087db96d56Sopenharmony_ci 23097db96d56Sopenharmony_ci self._assert_closed(fix) 23107db96d56Sopenharmony_ci # XXX Things slow down if we have too many interpreters. 23117db96d56Sopenharmony_ci fix.clean_up() 23127db96d56Sopenharmony_ci 23137db96d56Sopenharmony_ci def test_force_close(self): 23147db96d56Sopenharmony_ci for i, fix, actions in self._iter_close_tests(): 23157db96d56Sopenharmony_ci with self.subTest('{} {} {}'.format(i, fix, actions)): 23167db96d56Sopenharmony_ci fix.prep_interpreter(fix.interp) 23177db96d56Sopenharmony_ci self.run_actions(fix, actions) 23187db96d56Sopenharmony_ci 23197db96d56Sopenharmony_ci self._close(fix, force=True) 23207db96d56Sopenharmony_ci 23217db96d56Sopenharmony_ci self._assert_closed(fix) 23227db96d56Sopenharmony_ci # XXX Things slow down if we have too many interpreters. 23237db96d56Sopenharmony_ci fix.clean_up() 23247db96d56Sopenharmony_ci 23257db96d56Sopenharmony_ci 23267db96d56Sopenharmony_ciif __name__ == '__main__': 23277db96d56Sopenharmony_ci unittest.main() 2328