summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_capi.py
diff options
context:
space:
mode:
authorEric Snow <ericsnowcurrently@gmail.com>2017-05-23 02:46:40 (GMT)
committerGitHub <noreply@github.com>2017-05-23 02:46:40 (GMT)
commite377416c10eb0bf055b0728cdcdc4488fdfd3b5f (patch)
tree26dac18a3dfca605d0d09a61603b70a7d635e3b5 /Lib/test/test_capi.py
parent93fc20b73eea3da0b6305aaee951e5dd22d5c408 (diff)
downloadcpython-e377416c10eb0bf055b0728cdcdc4488fdfd3b5f.zip
cpython-e377416c10eb0bf055b0728cdcdc4488fdfd3b5f.tar.gz
cpython-e377416c10eb0bf055b0728cdcdc4488fdfd3b5f.tar.bz2
bpo-29102: Add a unique ID to PyInterpreterState. (#1639)
Diffstat (limited to 'Lib/test/test_capi.py')
-rw-r--r--Lib/test/test_capi.py91
1 files changed, 86 insertions, 5 deletions
diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py
index eb3e2c5..7660981 100644
--- a/Lib/test/test_capi.py
+++ b/Lib/test/test_capi.py
@@ -1,8 +1,10 @@
# Run the _testcapi module tests (tests for the Python/C API): by defn,
# these are all functions _testcapi exports whose name begins with 'test_'.
+from collections import namedtuple
import os
import pickle
+import platform
import random
import re
import subprocess
@@ -384,12 +386,91 @@ class EmbeddingTests(unittest.TestCase):
return out, err
def test_subinterps(self):
- # This is just a "don't crash" test
out, err = self.run_embedded_interpreter("repeated_init_and_subinterpreters")
- if support.verbose:
- print()
- print(out)
- print(err)
+ self.assertEqual(err, "")
+
+ # The output from _testembed looks like this:
+ # --- Pass 0 ---
+ # interp 0 <0x1cf9330>, thread state <0x1cf9700>: id(modules) = 139650431942728
+ # interp 1 <0x1d4f690>, thread state <0x1d35350>: id(modules) = 139650431165784
+ # interp 2 <0x1d5a690>, thread state <0x1d99ed0>: id(modules) = 139650413140368
+ # interp 3 <0x1d4f690>, thread state <0x1dc3340>: id(modules) = 139650412862200
+ # interp 0 <0x1cf9330>, thread state <0x1cf9700>: id(modules) = 139650431942728
+ # --- Pass 1 ---
+ # ...
+
+ interp_pat = (r"^interp (\d+) <(0x[\dA-F]+)>, "
+ r"thread state <(0x[\dA-F]+)>: "
+ r"id\(modules\) = ([\d]+)$")
+ Interp = namedtuple("Interp", "id interp tstate modules")
+
+ main = None
+ lastmain = None
+ numinner = None
+ numloops = 0
+ for line in out.splitlines():
+ if line == "--- Pass {} ---".format(numloops):
+ if numinner is not None:
+ self.assertEqual(numinner, 5)
+ if support.verbose:
+ print(line)
+ lastmain = main
+ main = None
+ mainid = 0
+ numloops += 1
+ numinner = 0
+ continue
+ numinner += 1
+
+ self.assertLessEqual(numinner, 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 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.
+ 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:
+ # 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)
@staticmethod
def _get_default_pipe_encoding():