Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit eec6060

Browse files
committed
Issue #10914: Add a minimal embedding test to test_capi.
2 parents f645451 + 72562d0 commit eec6060

5 files changed

Lines changed: 91 additions & 4 deletions

File tree

.hgignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,4 @@ PCbuild/*.suo
6969
PCbuild/Win32-temp-*
7070
PCbuild/x64-temp-*
7171
__pycache__
72+
Modules/_testembed

Lib/test/test_capi.py

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
# these are all functions _testcapi exports whose name begins with 'test_'.
33

44
from __future__ import with_statement
5+
import os
56
import random
67
import subprocess
78
import sys
@@ -141,8 +142,38 @@ class Test6012(unittest.TestCase):
141142
def test(self):
142143
self.assertEqual(_testcapi.argparsing("Hello", "World"), 1)
143144

145+
146+
class EmbeddingTest(unittest.TestCase):
147+
148+
def test_subinterps(self):
149+
# XXX only tested under Unix checkouts
150+
basepath = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
151+
oldcwd = os.getcwd()
152+
# This is needed otherwise we get a fatal error:
153+
# "Py_Initialize: Unable to get the locale encoding
154+
# LookupError: no codec search functions registered: can't find encoding"
155+
os.chdir(basepath)
156+
try:
157+
exe = os.path.join(basepath, "Modules", "_testembed")
158+
if not os.path.exists(exe):
159+
self.skipTest("%r doesn't exist" % exe)
160+
p = subprocess.Popen([exe],
161+
stdout=subprocess.PIPE,
162+
stderr=subprocess.PIPE)
163+
(out, err) = p.communicate()
164+
self.assertEqual(p.returncode, 0,
165+
"bad returncode %d, stderr is %r" %
166+
(p.returncode, err))
167+
if support.verbose:
168+
print()
169+
print(out.decode('latin1'))
170+
print(err.decode('latin1'))
171+
finally:
172+
os.chdir(oldcwd)
173+
174+
144175
def test_main():
145-
support.run_unittest(CAPITest)
176+
support.run_unittest(CAPITest, TestPendingCalls, Test6012, EmbeddingTest)
146177

147178
for name in dir(_testcapi):
148179
if name.startswith('test_'):
@@ -177,8 +208,6 @@ def callback():
177208
t.start()
178209
t.join()
179210

180-
support.run_unittest(TestPendingCalls, Test6012)
181-
182211

183212
if __name__ == "__main__":
184213
test_main()

Makefile.pre.in

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ LIBRARY_OBJS= \
394394

395395
# Default target
396396
all: build_all
397-
build_all: $(BUILDPYTHON) oldsharedmods sharedmods gdbhooks
397+
build_all: $(BUILDPYTHON) oldsharedmods sharedmods gdbhooks Modules/_testembed
398398

399399
# Compile a binary with gcc profile guided optimization.
400400
profile-opt:
@@ -539,6 +539,9 @@ Modules/Setup: $(srcdir)/Modules/Setup.dist
539539
echo "-----------------------------------------------"; \
540540
fi
541541

542+
Modules/_testembed: Modules/_testembed.o $(LIBRARY) $(LDLIBRARY) $(PY3LIBRARY)
543+
$(LINKCC) $(PY_LDFLAGS) $(LINKFORSHARED) -o $@ Modules/_testembed.o $(BLDLIBRARY) $(LIBS) $(MODLIBS) $(SYSLIBS) $(LDLAST)
544+
542545
############################################################################
543546
# Special rules for object files
544547

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,8 @@ Extensions
504504
Tests
505505
-----
506506

507+
- Issue #10914: Add a minimal embedding test to test_capi.
508+
507509
- Issue #11223: Skip test_lock_acquire_interruption() and
508510
test_rlock_acquire_interruption() of test_threadsignals if a thread lock is
509511
implemented using a POSIX mutex and a POSIX condition variable. A POSIX

Modules/_testembed.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#include <Python.h>
2+
#include <stdio.h>
3+
4+
void print_subinterp(void)
5+
{
6+
/* Just output some debug stuff */
7+
PyThreadState *ts = PyThreadState_Get();
8+
printf("interp %p, thread state %p: ", ts->interp, ts);
9+
fflush(stdout);
10+
PyRun_SimpleString(
11+
"import sys;"
12+
"print('id(modules) =', id(sys.modules));"
13+
"sys.stdout.flush()"
14+
);
15+
}
16+
17+
int main(int argc, char *argv[])
18+
{
19+
PyThreadState *mainstate, *substate;
20+
PyGILState_STATE gilstate;
21+
int i, j;
22+
23+
for (i=0; i<3; i++) {
24+
printf("--- Pass %d ---\n", i);
25+
/* HACK: the "./" at front avoids a search along the PATH in
26+
Modules/getpath.c */
27+
Py_SetProgramName(L"./_testembed");
28+
Py_Initialize();
29+
mainstate = PyThreadState_Get();
30+
31+
PyEval_InitThreads();
32+
PyEval_ReleaseThread(mainstate);
33+
34+
gilstate = PyGILState_Ensure();
35+
print_subinterp();
36+
PyThreadState_Swap(NULL);
37+
38+
for (j=0; j<3; j++) {
39+
substate = Py_NewInterpreter();
40+
print_subinterp();
41+
Py_EndInterpreter(substate);
42+
}
43+
44+
PyThreadState_Swap(mainstate);
45+
print_subinterp();
46+
PyGILState_Release(gilstate);
47+
48+
PyEval_RestoreThread(mainstate);
49+
Py_Finalize();
50+
}
51+
return 0;
52+
}

0 commit comments

Comments
 (0)