summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2011-04-25 19:21:07 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2011-04-25 19:21:07 (GMT)
commit8e6057769373a76fb8cead60f001ced38b635c5c (patch)
treeaa3059350c50f093f0984daad7e9feaddbd2ad15
parentb32321aed94bee8ea68fad79ed710670d0c1941c (diff)
downloadcpython-8e6057769373a76fb8cead60f001ced38b635c5c.zip
cpython-8e6057769373a76fb8cead60f001ced38b635c5c.tar.gz
cpython-8e6057769373a76fb8cead60f001ced38b635c5c.tar.bz2
Issue #10914: Add a minimal embedding test to test_capi.
-rw-r--r--.hgignore1
-rw-r--r--Lib/test/test_capi.py35
-rw-r--r--Makefile.pre.in5
-rw-r--r--Modules/_testembed.c52
4 files changed, 89 insertions, 4 deletions
diff --git a/.hgignore b/.hgignore
index 70aca54..e5e149f 100644
--- a/.hgignore
+++ b/.hgignore
@@ -64,3 +64,4 @@ PCbuild/*.ncb
PCbuild/*.bsc
PCbuild/Win32-temp-*
__pycache__
+Modules/_testembed
diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py
index f913347..327ac66 100644
--- a/Lib/test/test_capi.py
+++ b/Lib/test/test_capi.py
@@ -2,6 +2,7 @@
# these are all functions _testcapi exports whose name begins with 'test_'.
from __future__ import with_statement
+import os
import random
import subprocess
import sys
@@ -141,8 +142,38 @@ class Test6012(unittest.TestCase):
def test(self):
self.assertEqual(_testcapi.argparsing("Hello", "World"), 1)
+
+class EmbeddingTest(unittest.TestCase):
+
+ def test_subinterps(self):
+ # XXX only tested under Unix checkouts
+ basepath = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
+ oldcwd = os.getcwd()
+ # This is needed otherwise we get a fatal error:
+ # "Py_Initialize: Unable to get the locale encoding
+ # LookupError: no codec search functions registered: can't find encoding"
+ os.chdir(basepath)
+ try:
+ exe = os.path.join(basepath, "Modules", "_testembed")
+ if not os.path.exists(exe):
+ self.skipTest("%r doesn't exist" % exe)
+ p = subprocess.Popen([exe],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ (out, err) = p.communicate()
+ self.assertEqual(p.returncode, 0,
+ "bad returncode %d, stderr is %r" %
+ (p.returncode, err))
+ if support.verbose:
+ print()
+ print(out.decode('latin1'))
+ print(err.decode('latin1'))
+ finally:
+ os.chdir(oldcwd)
+
+
def test_main():
- support.run_unittest(CAPITest)
+ support.run_unittest(CAPITest, TestPendingCalls, Test6012, EmbeddingTest)
for name in dir(_testcapi):
if name.startswith('test_'):
@@ -177,8 +208,6 @@ def test_main():
t.start()
t.join()
- support.run_unittest(TestPendingCalls, Test6012)
-
if __name__ == "__main__":
test_main()
diff --git a/Makefile.pre.in b/Makefile.pre.in
index 7c23177..460c7c7 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -394,7 +394,7 @@ LIBRARY_OBJS= \
# Default target
all: build_all
-build_all: $(BUILDPYTHON) oldsharedmods sharedmods gdbhooks
+build_all: $(BUILDPYTHON) oldsharedmods sharedmods gdbhooks Modules/_testembed
# Compile a binary with gcc profile guided optimization.
profile-opt:
@@ -539,6 +539,9 @@ Modules/Setup: $(srcdir)/Modules/Setup.dist
echo "-----------------------------------------------"; \
fi
+Modules/_testembed: Modules/_testembed.o $(LIBRARY) $(LDLIBRARY) $(PY3LIBRARY)
+ $(LINKCC) $(PY_LDFLAGS) $(LINKFORSHARED) -o $@ Modules/_testembed.o $(BLDLIBRARY) $(LIBS) $(MODLIBS) $(SYSLIBS) $(LDLAST)
+
############################################################################
# Special rules for object files
diff --git a/Modules/_testembed.c b/Modules/_testembed.c
new file mode 100644
index 0000000..0df5ede
--- /dev/null
+++ b/Modules/_testembed.c
@@ -0,0 +1,52 @@
+#include <Python.h>
+#include <stdio.h>
+
+void print_subinterp(void)
+{
+ /* Just output some debug stuff */
+ PyThreadState *ts = PyThreadState_Get();
+ printf("interp %p, thread state %p: ", ts->interp, ts);
+ fflush(stdout);
+ PyRun_SimpleString(
+ "import sys;"
+ "print('id(modules) =', id(sys.modules));"
+ "sys.stdout.flush()"
+ );
+}
+
+int main(int argc, char *argv[])
+{
+ PyThreadState *mainstate, *substate;
+ PyGILState_STATE gilstate;
+ int i, j;
+
+ for (i=0; i<3; i++) {
+ printf("--- Pass %d ---\n", i);
+ /* HACK: the "./" at front avoids a search along the PATH in
+ Modules/getpath.c */
+ Py_SetProgramName(L"./_testembed");
+ Py_Initialize();
+ mainstate = PyThreadState_Get();
+
+ PyEval_InitThreads();
+ PyEval_ReleaseThread(mainstate);
+
+ gilstate = PyGILState_Ensure();
+ print_subinterp();
+ PyThreadState_Swap(NULL);
+
+ for (j=0; j<3; j++) {
+ substate = Py_NewInterpreter();
+ print_subinterp();
+ Py_EndInterpreter(substate);
+ }
+
+ PyThreadState_Swap(mainstate);
+ print_subinterp();
+ PyGILState_Release(gilstate);
+
+ PyEval_RestoreThread(mainstate);
+ Py_Finalize();
+ }
+ return 0;
+}