From 5ea2d0118e522b80dc5b0d4ef29772151babe7fd Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Wed, 24 May 2017 11:12:34 -0700 Subject: [PATCH 1/4] Use the correct printf format for int64_t. --- Programs/_testembed.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Programs/_testembed.c b/Programs/_testembed.c index de88404465a75b..c7660f95819ca8 100644 --- a/Programs/_testembed.c +++ b/Programs/_testembed.c @@ -28,7 +28,7 @@ static void print_subinterp(void) PyThreadState *ts = PyThreadState_Get(); PyInterpreterState *interp = ts->interp; int64_t id = PyInterpreterState_GetID(interp); - printf("interp %lu <0x%" PRIXPTR ">, thread state <0x%" PRIXPTR ">: ", + printf("interp %" PRId64 " <0x%" PRIXPTR ">, thread state <0x%" PRIXPTR ">: ", id, (uintptr_t)interp, (uintptr_t)ts); fflush(stdout); PyRun_SimpleString( From 94ad976493cd58cfd53f9db30a4400b9d5241fac Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Wed, 24 May 2017 11:13:10 -0700 Subject: [PATCH 2/4] Skip some subinterpreter checks on some platforms. --- Lib/test/test_capi.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py index 766098134c4ec6..68076e0f3cee7b 100644 --- a/Lib/test/test_capi.py +++ b/Lib/test/test_capi.py @@ -449,11 +449,12 @@ def test_subinterps(self): self.assertTrue(interp.interp) self.assertTrue(interp.tstate) self.assertTrue(interp.modules) - if platform.system() == 'Windows': - # XXX Fix on Windows: something is going on with the - # pointers in Programs/_testembed.c. interp.interp - # is 0x0 and # interp.modules is the same between - # interpreters. + if '0x0' in interp: + # XXX Fix on Windows (and other platforms): something + # is going on with the pointers in Programs/_testembed.c. + # interp.interp is 0x0 and interp.modules is the same + # between interpreters. + warnings.warn('platform prints pointers as 0x0; skipping...') continue if interp is main: if lastmain is not None: From e592cc79a9a00c755e91dee193694ea13877fbb7 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Wed, 24 May 2017 14:22:53 -0700 Subject: [PATCH 3/4] Split up test_subinterpreters into more specific tests. --- Lib/test/test_capi.py | 87 +++++++++++++++++++++++-------------------- 1 file changed, 47 insertions(+), 40 deletions(-) diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py index 68076e0f3cee7b..11fcd3cc1913a4 100644 --- a/Lib/test/test_capi.py +++ b/Lib/test/test_capi.py @@ -385,7 +385,7 @@ def run_embedded_interpreter(self, *args): (p.returncode, err)) return out, err - def test_subinterps(self): + def run_repeated_init_and_subinterpreters(self): out, err = self.run_embedded_interpreter("repeated_init_and_subinterpreters") self.assertEqual(err, "") @@ -404,74 +404,81 @@ def test_subinterps(self): r"id\(modules\) = ([\d]+)$") Interp = namedtuple("Interp", "id interp tstate modules") - main = None - lastmain = None - numinner = None numloops = 0 + current_run = [] for line in out.splitlines(): if line == "--- Pass {} ---".format(numloops): - if numinner is not None: - self.assertEqual(numinner, 5) + self.assertEqual(len(current_run), 0) if support.verbose: print(line) - lastmain = main - main = None - mainid = 0 numloops += 1 - numinner = 0 continue - numinner += 1 - self.assertLessEqual(numinner, 5) + self.assertLess(len(current_run), 5) match = re.match(interp_pat, line) if match is None: self.assertRegex(line, interp_pat) - # The last line in the loop should be the same as the first. - if numinner == 5: - self.assertEqual(match.groups(), main) - continue - # Parse the line from the loop. The first line is the main # interpreter and the 3 afterward are subinterpreters. interp = Interp(*match.groups()) if support.verbose: print(interp) - if numinner == 1: - main = interp - id = str(mainid) - else: - subid = mainid + numinner - 1 - id = str(subid) - - # Validate the loop line for each interpreter. - self.assertEqual(interp.id, id) self.assertTrue(interp.interp) self.assertTrue(interp.tstate) self.assertTrue(interp.modules) - if '0x0' in interp: + current_run.append(interp) + + # The last line in the loop should be the same as the first. + if len(current_run) == 5: + main = current_run[0] + self.assertEqual(interp, main) + yield current_run + current_run = [] + + def test_subinterps_main(self): + for run in self.run_repeated_init_and_subinterpreters(): + main = run[0] + + self.assertEqual(main.id, '0') + + def test_subinterps_different_ids(self): + for run in self.run_repeated_init_and_subinterpreters(): + main, *subs, _ = run + + mainid = int(main.id) + for i, sub in enumerate(subs): + self.assertEqual(sub.id, str(mainid + i + 1)) + + def test_subinterps_distinct_state(self): + lastmain = None + for run in self.run_repeated_init_and_subinterpreters(): + main, *subs, _ = run + + if '0x0' in main: # XXX Fix on Windows (and other platforms): something # is going on with the pointers in Programs/_testembed.c. # interp.interp is 0x0 and interp.modules is the same # between interpreters. - warnings.warn('platform prints pointers as 0x0; skipping...') - continue - if interp is main: - if lastmain is not None: - # A new main interpreter may have the same interp - # and/or tstate pointer as an earlier finalized/ - # destroyed one. So we do not check interp or - # tstate here. - self.assertNotEqual(interp.modules, lastmain.modules) - else: + raise unittest.SkipTest('platform prints pointers as 0x0') + + if lastmain is not None: + # A new main interpreter may have the same interp + # and/or tstate pointer as an earlier finalized/ + # destroyed one. So we do not check interp or + # tstate here. + self.assertNotEqual(main.modules, lastmain.modules) + lastmain = main + + for sub in subs: # A new subinterpreter may have the same # PyInterpreterState pointer as a previous one if # the earlier one has already been destroyed. So # we compare with the main interpreter. The same # applies to tstate. - self.assertNotEqual(interp.interp, main.interp) - self.assertNotEqual(interp.tstate, main.tstate) - self.assertNotEqual(interp.modules, main.modules) + self.assertNotEqual(sub.interp, main.interp) + self.assertNotEqual(sub.tstate, main.tstate) + self.assertNotEqual(sub.modules, main.modules) @staticmethod def _get_default_pipe_encoding(): From fbbe0a1866953097fe17ab4ef3fd86d1ad0399cc Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Wed, 24 May 2017 16:24:35 -0700 Subject: [PATCH 4/4] Don't compare main interpreters. --- Lib/test/test_capi.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py index 11fcd3cc1913a4..8ac8af98265695 100644 --- a/Lib/test/test_capi.py +++ b/Lib/test/test_capi.py @@ -451,7 +451,6 @@ def test_subinterps_different_ids(self): self.assertEqual(sub.id, str(mainid + i + 1)) def test_subinterps_distinct_state(self): - lastmain = None for run in self.run_repeated_init_and_subinterpreters(): main, *subs, _ = run @@ -462,14 +461,6 @@ def test_subinterps_distinct_state(self): # between interpreters. raise unittest.SkipTest('platform prints pointers as 0x0') - if lastmain is not None: - # A new main interpreter may have the same interp - # and/or tstate pointer as an earlier finalized/ - # destroyed one. So we do not check interp or - # tstate here. - self.assertNotEqual(main.modules, lastmain.modules) - lastmain = main - for sub in subs: # A new subinterpreter may have the same # PyInterpreterState pointer as a previous one if