blob: b12594799bfc93474bfc0801ceabea6f187298c0 [file] [log] [blame]
Antoine Pitrou8e605772011-04-25 21:21:07 +02001#include <Python.h>
Victor Stinnerb4d1e1f2017-11-30 22:05:00 +01002#include "pythread.h"
Eric Snowe3774162017-05-22 19:46:40 -07003#include <inttypes.h>
Antoine Pitrou8e605772011-04-25 21:21:07 +02004#include <stdio.h>
Nick Coghlanbc77eff2018-03-25 20:44:30 +10005#include <wchar.h>
Antoine Pitrou8e605772011-04-25 21:21:07 +02006
Nick Coghlan7d270ee2013-10-17 22:35:35 +10007/*********************************************************
8 * Embedded interpreter tests that need a custom exe
9 *
10 * Executed via 'EmbeddingTests' in Lib/test/test_capi.py
11 *********************************************************/
12
13static void _testembed_Py_Initialize(void)
14{
15 /* HACK: the "./" at front avoids a search along the PATH in
16 Modules/getpath.c */
17 Py_SetProgramName(L"./_testembed");
18 Py_Initialize();
19}
20
21
22/*****************************************************
Martin Panter8f265652016-04-19 04:03:41 +000023 * Test repeated initialisation and subinterpreters
Nick Coghlan7d270ee2013-10-17 22:35:35 +100024 *****************************************************/
25
26static void print_subinterp(void)
Antoine Pitrou8e605772011-04-25 21:21:07 +020027{
Eric Snowe3774162017-05-22 19:46:40 -070028 /* Output information about the interpreter in the format
29 expected in Lib/test/test_capi.py (test_subinterps). */
Antoine Pitrou8e605772011-04-25 21:21:07 +020030 PyThreadState *ts = PyThreadState_Get();
Eric Snowe3774162017-05-22 19:46:40 -070031 PyInterpreterState *interp = ts->interp;
32 int64_t id = PyInterpreterState_GetID(interp);
Eric Snowd1c3c132017-05-24 17:19:47 -070033 printf("interp %" PRId64 " <0x%" PRIXPTR ">, thread state <0x%" PRIXPTR ">: ",
Eric Snowe3774162017-05-22 19:46:40 -070034 id, (uintptr_t)interp, (uintptr_t)ts);
Antoine Pitrou8e605772011-04-25 21:21:07 +020035 fflush(stdout);
36 PyRun_SimpleString(
37 "import sys;"
38 "print('id(modules) =', id(sys.modules));"
39 "sys.stdout.flush()"
40 );
41}
42
Steve Dowerea74f0c2017-01-01 20:25:03 -080043static int test_repeated_init_and_subinterpreters(void)
Antoine Pitrou8e605772011-04-25 21:21:07 +020044{
45 PyThreadState *mainstate, *substate;
46 PyGILState_STATE gilstate;
47 int i, j;
48
Ned Deily939231b2016-08-16 00:17:42 -040049 for (i=0; i<15; i++) {
Antoine Pitrou8e605772011-04-25 21:21:07 +020050 printf("--- Pass %d ---\n", i);
Nick Coghlan7d270ee2013-10-17 22:35:35 +100051 _testembed_Py_Initialize();
Antoine Pitrou8e605772011-04-25 21:21:07 +020052 mainstate = PyThreadState_Get();
53
54 PyEval_InitThreads();
55 PyEval_ReleaseThread(mainstate);
56
57 gilstate = PyGILState_Ensure();
58 print_subinterp();
59 PyThreadState_Swap(NULL);
60
61 for (j=0; j<3; j++) {
62 substate = Py_NewInterpreter();
63 print_subinterp();
64 Py_EndInterpreter(substate);
65 }
66
67 PyThreadState_Swap(mainstate);
68 print_subinterp();
69 PyGILState_Release(gilstate);
Antoine Pitrou8e605772011-04-25 21:21:07 +020070
71 PyEval_RestoreThread(mainstate);
72 Py_Finalize();
73 }
Steve Dowerea74f0c2017-01-01 20:25:03 -080074 return 0;
Nick Coghlan7d270ee2013-10-17 22:35:35 +100075}
76
77/*****************************************************
78 * Test forcing a particular IO encoding
79 *****************************************************/
80
81static void check_stdio_details(const char *encoding, const char * errors)
82{
83 /* Output info for the test case to check */
84 if (encoding) {
85 printf("Expected encoding: %s\n", encoding);
86 } else {
87 printf("Expected encoding: default\n");
88 }
89 if (errors) {
90 printf("Expected errors: %s\n", errors);
91 } else {
92 printf("Expected errors: default\n");
93 }
94 fflush(stdout);
95 /* Force the given IO encoding */
96 Py_SetStandardStreamEncoding(encoding, errors);
97 _testembed_Py_Initialize();
98 PyRun_SimpleString(
99 "import sys;"
100 "print('stdin: {0.encoding}:{0.errors}'.format(sys.stdin));"
101 "print('stdout: {0.encoding}:{0.errors}'.format(sys.stdout));"
102 "print('stderr: {0.encoding}:{0.errors}'.format(sys.stderr));"
103 "sys.stdout.flush()"
104 );
105 Py_Finalize();
106}
107
Steve Dowerea74f0c2017-01-01 20:25:03 -0800108static int test_forced_io_encoding(void)
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000109{
110 /* Check various combinations */
111 printf("--- Use defaults ---\n");
112 check_stdio_details(NULL, NULL);
113 printf("--- Set errors only ---\n");
Victor Stinnerb2bef622014-03-18 02:38:12 +0100114 check_stdio_details(NULL, "ignore");
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000115 printf("--- Set encoding only ---\n");
Victor Stinner9e4994d2018-08-28 23:26:33 +0200116 check_stdio_details("iso8859-1", NULL);
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000117 printf("--- Set encoding and errors ---\n");
Victor Stinner9e4994d2018-08-28 23:26:33 +0200118 check_stdio_details("iso8859-1", "replace");
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000119
120 /* Check calling after initialization fails */
121 Py_Initialize();
122
123 if (Py_SetStandardStreamEncoding(NULL, NULL) == 0) {
124 printf("Unexpected success calling Py_SetStandardStreamEncoding");
125 }
126 Py_Finalize();
Steve Dowerea74f0c2017-01-01 20:25:03 -0800127 return 0;
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000128}
129
Victor Stinner9e87e772017-11-24 12:09:24 +0100130/*********************************************************
131 * Test parts of the C-API that work before initialization
132 *********************************************************/
133
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000134/* The pre-initialization tests tend to break by segfaulting, so explicitly
135 * flushed progress messages make the broken API easier to find when they fail.
136 */
137#define _Py_EMBED_PREINIT_CHECK(msg) \
138 do {printf(msg); fflush(stdout);} while (0);
139
Victor Stinner9e87e772017-11-24 12:09:24 +0100140static int test_pre_initialization_api(void)
141{
Victor Stinnera9df6512019-03-05 23:31:54 +0100142 /* the test doesn't support custom memory allocators */
143 putenv("PYTHONMALLOC=");
144
Nick Coghlan42746092017-11-26 14:19:13 +1000145 /* Leading "./" ensures getpath.c can still find the standard library */
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000146 _Py_EMBED_PREINIT_CHECK("Checking Py_DecodeLocale\n");
Nick Coghlan42746092017-11-26 14:19:13 +1000147 wchar_t *program = Py_DecodeLocale("./spam", NULL);
Victor Stinner9e87e772017-11-24 12:09:24 +0100148 if (program == NULL) {
149 fprintf(stderr, "Fatal error: cannot decode program name\n");
150 return 1;
151 }
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000152 _Py_EMBED_PREINIT_CHECK("Checking Py_SetProgramName\n");
Victor Stinner9e87e772017-11-24 12:09:24 +0100153 Py_SetProgramName(program);
154
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000155 _Py_EMBED_PREINIT_CHECK("Initializing interpreter\n");
Victor Stinner9e87e772017-11-24 12:09:24 +0100156 Py_Initialize();
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000157 _Py_EMBED_PREINIT_CHECK("Check sys module contents\n");
158 PyRun_SimpleString("import sys; "
159 "print('sys.executable:', sys.executable)");
160 _Py_EMBED_PREINIT_CHECK("Finalizing interpreter\n");
Victor Stinner9e87e772017-11-24 12:09:24 +0100161 Py_Finalize();
162
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000163 _Py_EMBED_PREINIT_CHECK("Freeing memory allocated by Py_DecodeLocale\n");
Victor Stinner9e87e772017-11-24 12:09:24 +0100164 PyMem_RawFree(program);
165 return 0;
166}
167
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000168
169/* bpo-33042: Ensure embedding apps can predefine sys module options */
170static int test_pre_initialization_sys_options(void)
171{
Nick Coghlan69f5c732018-03-30 15:36:42 +1000172 /* We allocate a couple of the options dynamically, and then delete
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000173 * them before calling Py_Initialize. This ensures the interpreter isn't
174 * relying on the caller to keep the passed in strings alive.
175 */
Nick Coghlan69f5c732018-03-30 15:36:42 +1000176 const wchar_t *static_warnoption = L"once";
177 const wchar_t *static_xoption = L"also_not_an_option=2";
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000178 size_t warnoption_len = wcslen(static_warnoption);
179 size_t xoption_len = wcslen(static_xoption);
Nick Coghlan69f5c732018-03-30 15:36:42 +1000180 wchar_t *dynamic_once_warnoption = \
181 (wchar_t *) calloc(warnoption_len+1, sizeof(wchar_t));
182 wchar_t *dynamic_xoption = \
183 (wchar_t *) calloc(xoption_len+1, sizeof(wchar_t));
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000184 wcsncpy(dynamic_once_warnoption, static_warnoption, warnoption_len+1);
185 wcsncpy(dynamic_xoption, static_xoption, xoption_len+1);
186
187 _Py_EMBED_PREINIT_CHECK("Checking PySys_AddWarnOption\n");
188 PySys_AddWarnOption(L"default");
189 _Py_EMBED_PREINIT_CHECK("Checking PySys_ResetWarnOptions\n");
190 PySys_ResetWarnOptions();
191 _Py_EMBED_PREINIT_CHECK("Checking PySys_AddWarnOption linked list\n");
192 PySys_AddWarnOption(dynamic_once_warnoption);
193 PySys_AddWarnOption(L"module");
194 PySys_AddWarnOption(L"default");
195 _Py_EMBED_PREINIT_CHECK("Checking PySys_AddXOption\n");
196 PySys_AddXOption(L"not_an_option=1");
197 PySys_AddXOption(dynamic_xoption);
198
199 /* Delete the dynamic options early */
200 free(dynamic_once_warnoption);
201 dynamic_once_warnoption = NULL;
202 free(dynamic_xoption);
203 dynamic_xoption = NULL;
204
205 _Py_EMBED_PREINIT_CHECK("Initializing interpreter\n");
206 _testembed_Py_Initialize();
207 _Py_EMBED_PREINIT_CHECK("Check sys module contents\n");
208 PyRun_SimpleString("import sys; "
209 "print('sys.warnoptions:', sys.warnoptions); "
210 "print('sys._xoptions:', sys._xoptions); "
211 "warnings = sys.modules['warnings']; "
212 "latest_filters = [f[0] for f in warnings.filters[:3]]; "
213 "print('warnings.filters[:3]:', latest_filters)");
214 _Py_EMBED_PREINIT_CHECK("Finalizing interpreter\n");
215 Py_Finalize();
216
217 return 0;
218}
219
220
221/* bpo-20891: Avoid race condition when initialising the GIL */
Victor Stinnerb4d1e1f2017-11-30 22:05:00 +0100222static void bpo20891_thread(void *lockp)
223{
224 PyThread_type_lock lock = *((PyThread_type_lock*)lockp);
225
226 PyGILState_STATE state = PyGILState_Ensure();
227 if (!PyGILState_Check()) {
228 fprintf(stderr, "PyGILState_Check failed!");
229 abort();
230 }
231
232 PyGILState_Release(state);
233
234 PyThread_release_lock(lock);
235
236 PyThread_exit_thread();
237}
238
239static int test_bpo20891(void)
240{
Victor Stinnera9df6512019-03-05 23:31:54 +0100241 /* the test doesn't support custom memory allocators */
242 putenv("PYTHONMALLOC=");
243
Victor Stinnerb4d1e1f2017-11-30 22:05:00 +0100244 /* bpo-20891: Calling PyGILState_Ensure in a non-Python thread before
245 calling PyEval_InitThreads() must not crash. PyGILState_Ensure() must
246 call PyEval_InitThreads() for us in this case. */
247 PyThread_type_lock lock = PyThread_allocate_lock();
248 if (!lock) {
249 fprintf(stderr, "PyThread_allocate_lock failed!");
250 return 1;
251 }
252
253 _testembed_Py_Initialize();
254
255 unsigned long thrd = PyThread_start_new_thread(bpo20891_thread, &lock);
256 if (thrd == PYTHREAD_INVALID_THREAD_ID) {
257 fprintf(stderr, "PyThread_start_new_thread failed!");
258 return 1;
259 }
260 PyThread_acquire_lock(lock, WAIT_LOCK);
261
262 Py_BEGIN_ALLOW_THREADS
263 /* wait until the thread exit */
264 PyThread_acquire_lock(lock, WAIT_LOCK);
265 Py_END_ALLOW_THREADS
266
267 PyThread_free_lock(lock);
268
269 return 0;
270}
271
Victor Stinner209abf72018-06-22 19:14:51 +0200272static int test_initialize_twice(void)
273{
274 _testembed_Py_Initialize();
275
276 /* bpo-33932: Calling Py_Initialize() twice should do nothing
277 * (and not crash!). */
278 Py_Initialize();
279
280 Py_Finalize();
281
282 return 0;
283}
284
Victor Stinnerfb47bca2018-07-20 17:34:23 +0200285static int test_initialize_pymain(void)
286{
287 wchar_t *argv[] = {L"PYTHON", L"-c",
288 L"import sys; print(f'Py_Main() after Py_Initialize: sys.argv={sys.argv}')",
289 L"arg2"};
290 _testembed_Py_Initialize();
291
292 /* bpo-34008: Calling Py_Main() after Py_Initialize() must not crash */
293 Py_Main(Py_ARRAY_LENGTH(argv), argv);
294
295 Py_Finalize();
296
297 return 0;
298}
299
Victor Stinner9e87e772017-11-24 12:09:24 +0100300
Victor Stinner00b137c2018-11-13 19:59:26 +0100301static void
302dump_config(void)
303{
Victor Stinner23bace22019-04-18 11:37:26 +0200304 (void) PyRun_SimpleStringFlags(
305 "import _testinternalcapi, json; "
306 "print(json.dumps(_testinternalcapi.get_configs()))",
307 0);
Victor Stinner00b137c2018-11-13 19:59:26 +0100308}
309
310
Victor Stinner56b29b62018-07-26 18:57:56 +0200311static int test_init_default_config(void)
312{
313 _testembed_Py_Initialize();
314 dump_config();
315 Py_Finalize();
316 return 0;
317}
318
319
320static int test_init_global_config(void)
321{
322 /* FIXME: test Py_IgnoreEnvironmentFlag */
323
324 putenv("PYTHONUTF8=0");
325 Py_UTF8Mode = 1;
326
327 /* Test initialization from global configuration variables (Py_xxx) */
328 Py_SetProgramName(L"./globalvar");
329
330 /* Py_IsolatedFlag is not tested */
331 Py_NoSiteFlag = 1;
332 Py_BytesWarningFlag = 1;
333
334 putenv("PYTHONINSPECT=");
335 Py_InspectFlag = 1;
336
337 putenv("PYTHONOPTIMIZE=0");
338 Py_InteractiveFlag = 1;
339
340 putenv("PYTHONDEBUG=0");
341 Py_OptimizeFlag = 2;
342
343 /* Py_DebugFlag is not tested */
344
345 putenv("PYTHONDONTWRITEBYTECODE=");
346 Py_DontWriteBytecodeFlag = 1;
347
348 putenv("PYTHONVERBOSE=0");
349 Py_VerboseFlag = 1;
350
351 Py_QuietFlag = 1;
352 Py_NoUserSiteDirectory = 1;
353
354 putenv("PYTHONUNBUFFERED=");
355 Py_UnbufferedStdioFlag = 1;
356
357 /* FIXME: test Py_LegacyWindowsFSEncodingFlag */
358 /* FIXME: test Py_LegacyWindowsStdioFlag */
359
Victor Stinner56b29b62018-07-26 18:57:56 +0200360 Py_Initialize();
361 dump_config();
362 Py_Finalize();
363 return 0;
364}
365
366
367static int test_init_from_config(void)
368{
Victor Stinner20004952019-03-26 02:31:11 +0100369 _PyInitError err;
370
371 _PyPreConfig preconfig = _PyPreConfig_INIT;
372
373 putenv("PYTHONMALLOC=malloc_debug");
374 preconfig.allocator = "malloc";
375
376 putenv("PYTHONUTF8=0");
377 Py_UTF8Mode = 0;
378 preconfig.utf8_mode = 1;
379
Victor Stinner5ac27a52019-03-27 13:40:14 +0100380 err = _Py_PreInitialize(&preconfig);
Victor Stinner20004952019-03-26 02:31:11 +0100381 if (_Py_INIT_FAILED(err)) {
382 _Py_ExitInitError(err);
383 }
384
Victor Stinner56b29b62018-07-26 18:57:56 +0200385 /* Test _Py_InitializeFromConfig() */
386 _PyCoreConfig config = _PyCoreConfig_INIT;
387 config.install_signal_handlers = 0;
388
389 /* FIXME: test use_environment */
390
391 putenv("PYTHONHASHSEED=42");
392 config.use_hash_seed = 1;
393 config.hash_seed = 123;
394
Victor Stinner56b29b62018-07-26 18:57:56 +0200395 /* dev_mode=1 is tested in test_init_dev_mode() */
396
397 putenv("PYTHONFAULTHANDLER=");
398 config.faulthandler = 1;
399
400 putenv("PYTHONTRACEMALLOC=0");
401 config.tracemalloc = 2;
402
403 putenv("PYTHONPROFILEIMPORTTIME=0");
404 config.import_time = 1;
405
406 config.show_ref_count = 1;
407 config.show_alloc_count = 1;
408 /* FIXME: test dump_refs: bpo-34223 */
409
410 putenv("PYTHONMALLOCSTATS=0");
411 config.malloc_stats = 1;
412
Victor Stinner56b29b62018-07-26 18:57:56 +0200413 putenv("PYTHONPYCACHEPREFIX=env_pycache_prefix");
414 config.pycache_prefix = L"conf_pycache_prefix";
415
416 Py_SetProgramName(L"./globalvar");
417 config.program_name = L"./conf_program_name";
418
Victor Stinner2f549082019-03-29 15:13:46 +0100419 static wchar_t* argv[] = {
420 L"python3",
Victor Stinner01de89c2018-11-14 17:39:45 +0100421 L"-c",
422 L"pass",
Victor Stinner2f549082019-03-29 15:13:46 +0100423 L"arg2",
Victor Stinner01de89c2018-11-14 17:39:45 +0100424 };
Victor Stinner74f65682019-03-15 15:08:05 +0100425 config.argv.length = Py_ARRAY_LENGTH(argv);
426 config.argv.items = argv;
Victor Stinner01de89c2018-11-14 17:39:45 +0100427
Victor Stinner56b29b62018-07-26 18:57:56 +0200428 config.program = L"conf_program";
Victor Stinner01de89c2018-11-14 17:39:45 +0100429
430 static wchar_t* xoptions[3] = {
431 L"core_xoption1=3",
432 L"core_xoption2=",
433 L"core_xoption3",
434 };
Victor Stinner74f65682019-03-15 15:08:05 +0100435 config.xoptions.length = Py_ARRAY_LENGTH(xoptions);
436 config.xoptions.items = xoptions;
Victor Stinner01de89c2018-11-14 17:39:45 +0100437
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100438 static wchar_t* warnoptions[1] = {
Victor Stinner01de89c2018-11-14 17:39:45 +0100439 L"error::ResourceWarning",
440 };
Victor Stinner74f65682019-03-15 15:08:05 +0100441 config.warnoptions.length = Py_ARRAY_LENGTH(warnoptions);
442 config.warnoptions.items = warnoptions;
Victor Stinner01de89c2018-11-14 17:39:45 +0100443
Victor Stinner56b29b62018-07-26 18:57:56 +0200444 /* FIXME: test module_search_path_env */
445 /* FIXME: test home */
446 /* FIXME: test path config: module_search_path .. dll_path */
447
448 putenv("PYTHONVERBOSE=0");
449 Py_VerboseFlag = 0;
450 config.verbose = 1;
451
452 Py_NoSiteFlag = 0;
453 config.site_import = 0;
454
455 Py_BytesWarningFlag = 0;
456 config.bytes_warning = 1;
457
458 putenv("PYTHONINSPECT=");
459 Py_InspectFlag = 0;
460 config.inspect = 1;
461
462 Py_InteractiveFlag = 0;
463 config.interactive = 1;
464
465 putenv("PYTHONOPTIMIZE=0");
466 Py_OptimizeFlag = 1;
467 config.optimization_level = 2;
468
Victor Stinner98512272018-08-01 03:07:00 +0200469 /* FIXME: test parser_debug */
Victor Stinner56b29b62018-07-26 18:57:56 +0200470
471 putenv("PYTHONDONTWRITEBYTECODE=");
472 Py_DontWriteBytecodeFlag = 0;
473 config.write_bytecode = 0;
474
475 Py_QuietFlag = 0;
476 config.quiet = 1;
477
478 putenv("PYTHONUNBUFFERED=");
479 Py_UnbufferedStdioFlag = 0;
Victor Stinner98512272018-08-01 03:07:00 +0200480 config.buffered_stdio = 0;
Victor Stinner56b29b62018-07-26 18:57:56 +0200481
Victor Stinnerdfe0dc72018-08-29 11:47:29 +0200482 putenv("PYTHONIOENCODING=cp424");
483 Py_SetStandardStreamEncoding("ascii", "ignore");
Victor Stinner01de89c2018-11-14 17:39:45 +0100484#ifdef MS_WINDOWS
485 /* Py_SetStandardStreamEncoding() sets Py_LegacyWindowsStdioFlag to 1.
486 Force it to 0 through the config. */
487 config.legacy_windows_stdio = 0;
488#endif
Victor Stinner709d23d2019-05-02 14:56:30 -0400489 config.stdio_encoding = L"iso8859-1";
490 config.stdio_errors = L"replace";
Victor Stinnerdfe0dc72018-08-29 11:47:29 +0200491
Victor Stinner56b29b62018-07-26 18:57:56 +0200492 putenv("PYTHONNOUSERSITE=");
493 Py_NoUserSiteDirectory = 0;
494 config.user_site_directory = 0;
495
Victor Stinnercb9fbd32019-05-01 23:51:56 -0400496 config.check_hash_pycs_mode = L"always";
Victor Stinner56b29b62018-07-26 18:57:56 +0200497
Victor Stinner5ac27a52019-03-27 13:40:14 +0100498 err = _Py_InitializeFromConfig(&config);
Victor Stinner56b29b62018-07-26 18:57:56 +0200499 if (_Py_INIT_FAILED(err)) {
Victor Stinnerdfe88472019-03-01 12:14:41 +0100500 _Py_ExitInitError(err);
Victor Stinner56b29b62018-07-26 18:57:56 +0200501 }
502 dump_config();
503 Py_Finalize();
504 return 0;
505}
506
507
508static void test_init_env_putenvs(void)
509{
510 putenv("PYTHONHASHSEED=42");
Victor Stinner25d13f32019-03-06 12:51:53 +0100511 putenv("PYTHONMALLOC=malloc");
Victor Stinner56b29b62018-07-26 18:57:56 +0200512 putenv("PYTHONTRACEMALLOC=2");
513 putenv("PYTHONPROFILEIMPORTTIME=1");
514 putenv("PYTHONMALLOCSTATS=1");
515 putenv("PYTHONUTF8=1");
516 putenv("PYTHONVERBOSE=1");
517 putenv("PYTHONINSPECT=1");
518 putenv("PYTHONOPTIMIZE=2");
519 putenv("PYTHONDONTWRITEBYTECODE=1");
520 putenv("PYTHONUNBUFFERED=1");
521 putenv("PYTHONPYCACHEPREFIX=env_pycache_prefix");
522 putenv("PYTHONNOUSERSITE=1");
523 putenv("PYTHONFAULTHANDLER=1");
Victor Stinnerdfe0dc72018-08-29 11:47:29 +0200524 putenv("PYTHONIOENCODING=iso8859-1:replace");
Victor Stinner56b29b62018-07-26 18:57:56 +0200525 /* FIXME: test PYTHONWARNINGS */
526 /* FIXME: test PYTHONEXECUTABLE */
527 /* FIXME: test PYTHONHOME */
528 /* FIXME: test PYTHONDEBUG */
529 /* FIXME: test PYTHONDUMPREFS */
530 /* FIXME: test PYTHONCOERCECLOCALE */
531 /* FIXME: test PYTHONPATH */
532}
533
534
535static int test_init_env(void)
536{
537 /* Test initialization from environment variables */
538 Py_IgnoreEnvironmentFlag = 0;
539 test_init_env_putenvs();
540 _testembed_Py_Initialize();
541 dump_config();
542 Py_Finalize();
543 return 0;
544}
545
546
Victor Stinner25d13f32019-03-06 12:51:53 +0100547static void test_init_env_dev_mode_putenvs(void)
548{
549 test_init_env_putenvs();
550 putenv("PYTHONMALLOC=");
551 putenv("PYTHONFAULTHANDLER=");
552 putenv("PYTHONDEVMODE=1");
553}
554
555
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100556static int test_init_env_dev_mode(void)
557{
558 /* Test initialization from environment variables */
559 Py_IgnoreEnvironmentFlag = 0;
560 test_init_env_dev_mode_putenvs();
561 _testembed_Py_Initialize();
562 dump_config();
563 Py_Finalize();
564 return 0;
565}
566
567
Victor Stinner25d13f32019-03-06 12:51:53 +0100568static int test_init_env_dev_mode_alloc(void)
569{
570 /* Test initialization from environment variables */
571 Py_IgnoreEnvironmentFlag = 0;
572 test_init_env_dev_mode_putenvs();
573 putenv("PYTHONMALLOC=malloc");
574 _testembed_Py_Initialize();
575 dump_config();
576 Py_Finalize();
577 return 0;
578}
579
580
Victor Stinner56b29b62018-07-26 18:57:56 +0200581static int test_init_isolated(void)
582{
Victor Stinner20004952019-03-26 02:31:11 +0100583 _PyInitError err;
584
Victor Stinner56b29b62018-07-26 18:57:56 +0200585 /* Test _PyCoreConfig.isolated=1 */
586 _PyCoreConfig config = _PyCoreConfig_INIT;
587
Victor Stinnercad1f742019-03-05 02:01:27 +0100588 Py_IsolatedFlag = 0;
Victor Stinner20004952019-03-26 02:31:11 +0100589 config.isolated = 1;
Victor Stinnercad1f742019-03-05 02:01:27 +0100590
Victor Stinner56b29b62018-07-26 18:57:56 +0200591 /* Use path starting with "./" avoids a search along the PATH */
592 config.program_name = L"./_testembed";
593
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100594 test_init_env_dev_mode_putenvs();
Victor Stinner5ac27a52019-03-27 13:40:14 +0100595 err = _Py_InitializeFromConfig(&config);
Victor Stinner56b29b62018-07-26 18:57:56 +0200596 if (_Py_INIT_FAILED(err)) {
Victor Stinnerdfe88472019-03-01 12:14:41 +0100597 _Py_ExitInitError(err);
Victor Stinner56b29b62018-07-26 18:57:56 +0200598 }
599 dump_config();
600 Py_Finalize();
601 return 0;
602}
603
604
Victor Stinner6da20a42019-03-27 00:26:18 +0100605/* _PyPreConfig.isolated=1, _PyCoreConfig.isolated=0 */
606static int test_preinit_isolated1(void)
607{
608 _PyInitError err;
609
610 _PyPreConfig preconfig = _PyPreConfig_INIT;
Victor Stinner6da20a42019-03-27 00:26:18 +0100611 preconfig.isolated = 1;
612
Victor Stinner5ac27a52019-03-27 13:40:14 +0100613 err = _Py_PreInitialize(&preconfig);
Victor Stinner6da20a42019-03-27 00:26:18 +0100614 if (_Py_INIT_FAILED(err)) {
615 _Py_ExitInitError(err);
616 }
617
618 _PyCoreConfig config = _PyCoreConfig_INIT;
619 config.program_name = L"./_testembed";
620
621 test_init_env_dev_mode_putenvs();
Victor Stinner5ac27a52019-03-27 13:40:14 +0100622 err = _Py_InitializeFromConfig(&config);
Victor Stinner6da20a42019-03-27 00:26:18 +0100623 if (_Py_INIT_FAILED(err)) {
624 _Py_ExitInitError(err);
625 }
626 dump_config();
627 Py_Finalize();
628 return 0;
629}
630
631
632/* _PyPreConfig.isolated=0, _PyCoreConfig.isolated=1 */
633static int test_preinit_isolated2(void)
634{
635 _PyInitError err;
636
637 _PyPreConfig preconfig = _PyPreConfig_INIT;
Victor Stinner6da20a42019-03-27 00:26:18 +0100638 preconfig.isolated = 0;
639
Victor Stinner5ac27a52019-03-27 13:40:14 +0100640 err = _Py_PreInitialize(&preconfig);
Victor Stinner6da20a42019-03-27 00:26:18 +0100641 if (_Py_INIT_FAILED(err)) {
642 _Py_ExitInitError(err);
643 }
644
645 /* Test _PyCoreConfig.isolated=1 */
646 _PyCoreConfig config = _PyCoreConfig_INIT;
647
648 Py_IsolatedFlag = 0;
649 config.isolated = 1;
650
651 /* Use path starting with "./" avoids a search along the PATH */
652 config.program_name = L"./_testembed";
653
654 test_init_env_dev_mode_putenvs();
Victor Stinner5ac27a52019-03-27 13:40:14 +0100655 err = _Py_InitializeFromConfig(&config);
Victor Stinner6da20a42019-03-27 00:26:18 +0100656 if (_Py_INIT_FAILED(err)) {
657 _Py_ExitInitError(err);
658 }
659 dump_config();
660 Py_Finalize();
661 return 0;
662}
663
664
Victor Stinner56b29b62018-07-26 18:57:56 +0200665static int test_init_dev_mode(void)
666{
667 _PyCoreConfig config = _PyCoreConfig_INIT;
668 putenv("PYTHONFAULTHANDLER=");
669 putenv("PYTHONMALLOC=");
Victor Stinner20004952019-03-26 02:31:11 +0100670 config.dev_mode = 1;
Victor Stinner56b29b62018-07-26 18:57:56 +0200671 config.program_name = L"./_testembed";
Victor Stinner5ac27a52019-03-27 13:40:14 +0100672 _PyInitError err = _Py_InitializeFromConfig(&config);
Victor Stinner56b29b62018-07-26 18:57:56 +0200673 if (_Py_INIT_FAILED(err)) {
Victor Stinnerdfe88472019-03-01 12:14:41 +0100674 _Py_ExitInitError(err);
Victor Stinner56b29b62018-07-26 18:57:56 +0200675 }
676 dump_config();
677 Py_Finalize();
678 return 0;
679}
680
681
Victor Stinner2f549082019-03-29 15:13:46 +0100682static int test_run_main(void)
683{
684 _PyCoreConfig config = _PyCoreConfig_INIT;
685
686 wchar_t *argv[] = {L"python3", L"-c",
687 (L"import sys; "
688 L"print(f'_Py_RunMain(): sys.argv={sys.argv}')"),
689 L"arg2"};
690 config.argv.length = Py_ARRAY_LENGTH(argv);
691 config.argv.items = argv;
692 config.program_name = L"./python3";
693
694 _PyInitError err = _Py_InitializeFromConfig(&config);
695 if (_Py_INIT_FAILED(err)) {
696 _Py_ExitInitError(err);
697 }
698
699 return _Py_RunMain();
700}
701
702
Steve Dowerea74f0c2017-01-01 20:25:03 -0800703/* *********************************************************
704 * List of test cases and the function that implements it.
Serhiy Storchaka13ad3b72017-09-14 09:38:36 +0300705 *
Steve Dowerea74f0c2017-01-01 20:25:03 -0800706 * Names are compared case-sensitively with the first
707 * argument. If no match is found, or no first argument was
708 * provided, the names of all test cases are printed and
709 * the exit code will be -1.
710 *
711 * The int returned from test functions is used as the exit
712 * code, and test_capi treats all non-zero exit codes as a
Serhiy Storchaka13ad3b72017-09-14 09:38:36 +0300713 * failed test.
Steve Dowerea74f0c2017-01-01 20:25:03 -0800714 *********************************************************/
715struct TestCase
716{
717 const char *name;
718 int (*func)(void);
719};
720
721static struct TestCase TestCases[] = {
722 { "forced_io_encoding", test_forced_io_encoding },
723 { "repeated_init_and_subinterpreters", test_repeated_init_and_subinterpreters },
Victor Stinner9e87e772017-11-24 12:09:24 +0100724 { "pre_initialization_api", test_pre_initialization_api },
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000725 { "pre_initialization_sys_options", test_pre_initialization_sys_options },
Victor Stinnerb4d1e1f2017-11-30 22:05:00 +0100726 { "bpo20891", test_bpo20891 },
Victor Stinner209abf72018-06-22 19:14:51 +0200727 { "initialize_twice", test_initialize_twice },
Victor Stinnerfb47bca2018-07-20 17:34:23 +0200728 { "initialize_pymain", test_initialize_pymain },
Victor Stinner56b29b62018-07-26 18:57:56 +0200729 { "init_default_config", test_init_default_config },
730 { "init_global_config", test_init_global_config },
731 { "init_from_config", test_init_from_config },
732 { "init_env", test_init_env },
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100733 { "init_env_dev_mode", test_init_env_dev_mode },
Victor Stinner25d13f32019-03-06 12:51:53 +0100734 { "init_env_dev_mode_alloc", test_init_env_dev_mode_alloc },
Victor Stinner56b29b62018-07-26 18:57:56 +0200735 { "init_dev_mode", test_init_dev_mode },
736 { "init_isolated", test_init_isolated },
Victor Stinner6da20a42019-03-27 00:26:18 +0100737 { "preinit_isolated1", test_preinit_isolated1 },
738 { "preinit_isolated2", test_preinit_isolated2 },
Victor Stinner2f549082019-03-29 15:13:46 +0100739 { "run_main", test_run_main },
Steve Dowerea74f0c2017-01-01 20:25:03 -0800740 { NULL, NULL }
741};
742
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000743int main(int argc, char *argv[])
744{
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000745 if (argc > 1) {
Steve Dowerea74f0c2017-01-01 20:25:03 -0800746 for (struct TestCase *tc = TestCases; tc && tc->name; tc++) {
747 if (strcmp(argv[1], tc->name) == 0)
748 return (*tc->func)();
749 }
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000750 }
Steve Dowerea74f0c2017-01-01 20:25:03 -0800751
752 /* No match found, or no test name provided, so display usage */
753 printf("Python " PY_VERSION " _testembed executable for embedded interpreter tests\n"
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000754 "Normally executed via 'EmbeddingTests' in Lib/test/test_embed.py\n\n"
Steve Dowerea74f0c2017-01-01 20:25:03 -0800755 "Usage: %s TESTNAME\n\nAll available tests:\n", argv[0]);
756 for (struct TestCase *tc = TestCases; tc && tc->name; tc++) {
757 printf(" %s\n", tc->name);
758 }
759
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000760 /* Non-zero exit code will cause test_embed.py tests to fail.
Steve Dowerea74f0c2017-01-01 20:25:03 -0800761 This is intentional. */
762 return -1;
Antoine Pitrou8e605772011-04-25 21:21:07 +0200763}