blob: a68d4fa25f7cd05f8d112e6b0d286e64d7eef392 [file] [log] [blame]
Antoine Pitrou8e605772011-04-25 21:21:07 +02001#include <Python.h>
2#include <stdio.h>
3
Nick Coghlan7d270ee2013-10-17 22:35:35 +10004/*********************************************************
5 * Embedded interpreter tests that need a custom exe
6 *
7 * Executed via 'EmbeddingTests' in Lib/test/test_capi.py
8 *********************************************************/
9
10static void _testembed_Py_Initialize(void)
11{
12 /* HACK: the "./" at front avoids a search along the PATH in
13 Modules/getpath.c */
14 Py_SetProgramName(L"./_testembed");
15 Py_Initialize();
16}
17
18
19/*****************************************************
Martin Panter8f265652016-04-19 04:03:41 +000020 * Test repeated initialisation and subinterpreters
Nick Coghlan7d270ee2013-10-17 22:35:35 +100021 *****************************************************/
22
23static void print_subinterp(void)
Antoine Pitrou8e605772011-04-25 21:21:07 +020024{
25 /* Just output some debug stuff */
26 PyThreadState *ts = PyThreadState_Get();
27 printf("interp %p, thread state %p: ", ts->interp, ts);
28 fflush(stdout);
29 PyRun_SimpleString(
30 "import sys;"
31 "print('id(modules) =', id(sys.modules));"
32 "sys.stdout.flush()"
33 );
34}
35
Steve Dowerea74f0c2017-01-01 20:25:03 -080036static int test_repeated_init_and_subinterpreters(void)
Antoine Pitrou8e605772011-04-25 21:21:07 +020037{
38 PyThreadState *mainstate, *substate;
Victor Stinner66299a42011-04-26 23:37:02 +020039#ifdef WITH_THREAD
Antoine Pitrou8e605772011-04-25 21:21:07 +020040 PyGILState_STATE gilstate;
Victor Stinner66299a42011-04-26 23:37:02 +020041#endif
Antoine Pitrou8e605772011-04-25 21:21:07 +020042 int i, j;
43
Ned Deily939231b2016-08-16 00:17:42 -040044 for (i=0; i<15; i++) {
Antoine Pitrou8e605772011-04-25 21:21:07 +020045 printf("--- Pass %d ---\n", i);
Nick Coghlan7d270ee2013-10-17 22:35:35 +100046 _testembed_Py_Initialize();
Antoine Pitrou8e605772011-04-25 21:21:07 +020047 mainstate = PyThreadState_Get();
48
Victor Stinner66299a42011-04-26 23:37:02 +020049#ifdef WITH_THREAD
Antoine Pitrou8e605772011-04-25 21:21:07 +020050 PyEval_InitThreads();
51 PyEval_ReleaseThread(mainstate);
52
53 gilstate = PyGILState_Ensure();
Victor Stinner66299a42011-04-26 23:37:02 +020054#endif
Antoine Pitrou8e605772011-04-25 21:21:07 +020055 print_subinterp();
56 PyThreadState_Swap(NULL);
57
58 for (j=0; j<3; j++) {
59 substate = Py_NewInterpreter();
60 print_subinterp();
61 Py_EndInterpreter(substate);
62 }
63
64 PyThreadState_Swap(mainstate);
65 print_subinterp();
Victor Stinner66299a42011-04-26 23:37:02 +020066#ifdef WITH_THREAD
Antoine Pitrou8e605772011-04-25 21:21:07 +020067 PyGILState_Release(gilstate);
Victor Stinner66299a42011-04-26 23:37:02 +020068#endif
Antoine Pitrou8e605772011-04-25 21:21:07 +020069
70 PyEval_RestoreThread(mainstate);
71 Py_Finalize();
72 }
Steve Dowerea74f0c2017-01-01 20:25:03 -080073 return 0;
Nick Coghlan7d270ee2013-10-17 22:35:35 +100074}
75
76/*****************************************************
77 * Test forcing a particular IO encoding
78 *****************************************************/
79
80static void check_stdio_details(const char *encoding, const char * errors)
81{
82 /* Output info for the test case to check */
83 if (encoding) {
84 printf("Expected encoding: %s\n", encoding);
85 } else {
86 printf("Expected encoding: default\n");
87 }
88 if (errors) {
89 printf("Expected errors: %s\n", errors);
90 } else {
91 printf("Expected errors: default\n");
92 }
93 fflush(stdout);
94 /* Force the given IO encoding */
95 Py_SetStandardStreamEncoding(encoding, errors);
96 _testembed_Py_Initialize();
97 PyRun_SimpleString(
98 "import sys;"
99 "print('stdin: {0.encoding}:{0.errors}'.format(sys.stdin));"
100 "print('stdout: {0.encoding}:{0.errors}'.format(sys.stdout));"
101 "print('stderr: {0.encoding}:{0.errors}'.format(sys.stderr));"
102 "sys.stdout.flush()"
103 );
104 Py_Finalize();
105}
106
Steve Dowerea74f0c2017-01-01 20:25:03 -0800107static int test_forced_io_encoding(void)
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000108{
109 /* Check various combinations */
110 printf("--- Use defaults ---\n");
111 check_stdio_details(NULL, NULL);
112 printf("--- Set errors only ---\n");
Victor Stinnerb2bef622014-03-18 02:38:12 +0100113 check_stdio_details(NULL, "ignore");
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000114 printf("--- Set encoding only ---\n");
115 check_stdio_details("latin-1", NULL);
116 printf("--- Set encoding and errors ---\n");
Victor Stinnerb2bef622014-03-18 02:38:12 +0100117 check_stdio_details("latin-1", "replace");
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000118
119 /* Check calling after initialization fails */
120 Py_Initialize();
121
122 if (Py_SetStandardStreamEncoding(NULL, NULL) == 0) {
123 printf("Unexpected success calling Py_SetStandardStreamEncoding");
124 }
125 Py_Finalize();
Steve Dowerea74f0c2017-01-01 20:25:03 -0800126 return 0;
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000127}
128
Steve Dowerea74f0c2017-01-01 20:25:03 -0800129/* *********************************************************
130 * List of test cases and the function that implements it.
131 *
132 * Names are compared case-sensitively with the first
133 * argument. If no match is found, or no first argument was
134 * provided, the names of all test cases are printed and
135 * the exit code will be -1.
136 *
137 * The int returned from test functions is used as the exit
138 * code, and test_capi treats all non-zero exit codes as a
139 * failed test.
140 *********************************************************/
141struct TestCase
142{
143 const char *name;
144 int (*func)(void);
145};
146
147static struct TestCase TestCases[] = {
148 { "forced_io_encoding", test_forced_io_encoding },
149 { "repeated_init_and_subinterpreters", test_repeated_init_and_subinterpreters },
150 { NULL, NULL }
151};
152
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000153int main(int argc, char *argv[])
154{
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000155 if (argc > 1) {
Steve Dowerea74f0c2017-01-01 20:25:03 -0800156 for (struct TestCase *tc = TestCases; tc && tc->name; tc++) {
157 if (strcmp(argv[1], tc->name) == 0)
158 return (*tc->func)();
159 }
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000160 }
Steve Dowerea74f0c2017-01-01 20:25:03 -0800161
162 /* No match found, or no test name provided, so display usage */
163 printf("Python " PY_VERSION " _testembed executable for embedded interpreter tests\n"
164 "Normally executed via 'EmbeddingTests' in Lib/test/test_capi.py\n\n"
165 "Usage: %s TESTNAME\n\nAll available tests:\n", argv[0]);
166 for (struct TestCase *tc = TestCases; tc && tc->name; tc++) {
167 printf(" %s\n", tc->name);
168 }
169
170 /* Non-zero exit code will cause test_capi.py tests to fail.
171 This is intentional. */
172 return -1;
Antoine Pitrou8e605772011-04-25 21:21:07 +0200173}