1. Armin Rigo
  2. cpython-withatomic

Commits

Antoine Pitrou  committed d195ff5

Issue #10914: Add a minimal embedding test to test_capi.

  • Participants
  • Parent commits 66ef5e8
  • Branches 3.2

Comments (0)

Files changed (4)

File .hgignore

View file
 PCbuild/*.bsc
 PCbuild/Win32-temp-*
 __pycache__
+Modules/_testembed

File Lib/test/test_capi.py

View file
 # these are all functions _testcapi exports whose name begins with 'test_'.
 
 from __future__ import with_statement
+import os
 import random
 import subprocess
 import sys
     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_'):
         t.start()
         t.join()
 
-    support.run_unittest(TestPendingCalls, Test6012)
-
 
 if __name__ == "__main__":
     test_main()

File Makefile.pre.in

View file
 
 # 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:
 		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
 

File Modules/_testembed.c

View file
+#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;
+}