blob: f8de6bc07934bce46339b28ad72cc031b2e56921 [file] [log] [blame]
Victor Stinner91c99872019-05-14 22:01:51 +02001#ifndef Py_BUILD_CORE_MODULE
2# define Py_BUILD_CORE_MODULE
3#endif
4
Victor Stinner013a18a2019-06-06 14:25:18 +02005/* Always enable assertion (even in release mode) */
6#undef NDEBUG
7
Antoine Pitrou8e605772011-04-25 21:21:07 +02008#include <Python.h>
Victor Stinnere5014be2020-04-14 17:52:15 +02009#include "pycore_initconfig.h" // _PyConfig_InitCompatConfig()
10#include "pycore_runtime.h" // _PyRuntime
Victor Stinnerbab0db62019-05-18 03:21:27 +020011#include <Python.h>
Eric Snowe3774162017-05-22 19:46:40 -070012#include <inttypes.h>
Antoine Pitrou8e605772011-04-25 21:21:07 +020013#include <stdio.h>
Nick Coghlanbc77eff2018-03-25 20:44:30 +100014#include <wchar.h>
Antoine Pitrou8e605772011-04-25 21:21:07 +020015
Nick Coghlan7d270ee2013-10-17 22:35:35 +100016/*********************************************************
17 * Embedded interpreter tests that need a custom exe
18 *
19 * Executed via 'EmbeddingTests' in Lib/test/test_capi.py
20 *********************************************************/
21
Victor Stinnerbb6bf7d2019-09-24 18:21:02 +020022/* Use path starting with "./" avoids a search along the PATH */
23#define PROGRAM_NAME L"./_testembed"
24
Victor Stinnerece38412021-06-23 17:47:38 +020025#define INIT_LOOPS 16
26
27
Nick Coghlan7d270ee2013-10-17 22:35:35 +100028static void _testembed_Py_Initialize(void)
29{
Victor Stinnerbb6bf7d2019-09-24 18:21:02 +020030 Py_SetProgramName(PROGRAM_NAME);
Nick Coghlan7d270ee2013-10-17 22:35:35 +100031 Py_Initialize();
32}
33
34
35/*****************************************************
Martin Panter8f265652016-04-19 04:03:41 +000036 * Test repeated initialisation and subinterpreters
Nick Coghlan7d270ee2013-10-17 22:35:35 +100037 *****************************************************/
38
39static void print_subinterp(void)
Antoine Pitrou8e605772011-04-25 21:21:07 +020040{
Eric Snowe3774162017-05-22 19:46:40 -070041 /* Output information about the interpreter in the format
42 expected in Lib/test/test_capi.py (test_subinterps). */
Antoine Pitrou8e605772011-04-25 21:21:07 +020043 PyThreadState *ts = PyThreadState_Get();
Eric Snowe3774162017-05-22 19:46:40 -070044 PyInterpreterState *interp = ts->interp;
45 int64_t id = PyInterpreterState_GetID(interp);
Eric Snowd1c3c132017-05-24 17:19:47 -070046 printf("interp %" PRId64 " <0x%" PRIXPTR ">, thread state <0x%" PRIXPTR ">: ",
Eric Snowe3774162017-05-22 19:46:40 -070047 id, (uintptr_t)interp, (uintptr_t)ts);
Antoine Pitrou8e605772011-04-25 21:21:07 +020048 fflush(stdout);
49 PyRun_SimpleString(
50 "import sys;"
51 "print('id(modules) =', id(sys.modules));"
52 "sys.stdout.flush()"
53 );
54}
55
Steve Dowerea74f0c2017-01-01 20:25:03 -080056static int test_repeated_init_and_subinterpreters(void)
Antoine Pitrou8e605772011-04-25 21:21:07 +020057{
58 PyThreadState *mainstate, *substate;
59 PyGILState_STATE gilstate;
Antoine Pitrou8e605772011-04-25 21:21:07 +020060
Victor Stinnerece38412021-06-23 17:47:38 +020061 for (int i=1; i <= INIT_LOOPS; i++) {
Antoine Pitrou8e605772011-04-25 21:21:07 +020062 printf("--- Pass %d ---\n", i);
Nick Coghlan7d270ee2013-10-17 22:35:35 +100063 _testembed_Py_Initialize();
Antoine Pitrou8e605772011-04-25 21:21:07 +020064 mainstate = PyThreadState_Get();
65
Antoine Pitrou8e605772011-04-25 21:21:07 +020066 PyEval_ReleaseThread(mainstate);
67
68 gilstate = PyGILState_Ensure();
69 print_subinterp();
70 PyThreadState_Swap(NULL);
71
Victor Stinnerece38412021-06-23 17:47:38 +020072 for (int j=0; j<3; j++) {
Antoine Pitrou8e605772011-04-25 21:21:07 +020073 substate = Py_NewInterpreter();
74 print_subinterp();
75 Py_EndInterpreter(substate);
76 }
77
78 PyThreadState_Swap(mainstate);
79 print_subinterp();
80 PyGILState_Release(gilstate);
Antoine Pitrou8e605772011-04-25 21:21:07 +020081
82 PyEval_RestoreThread(mainstate);
83 Py_Finalize();
84 }
Steve Dowerea74f0c2017-01-01 20:25:03 -080085 return 0;
Nick Coghlan7d270ee2013-10-17 22:35:35 +100086}
87
Victor Stinnerece38412021-06-23 17:47:38 +020088#define EMBEDDED_EXT_NAME "embedded_ext"
89
90static PyModuleDef embedded_ext = {
91 PyModuleDef_HEAD_INIT,
92 .m_name = EMBEDDED_EXT_NAME,
93 .m_size = 0,
94};
95
96static PyObject*
97PyInit_embedded_ext(void)
98{
99 return PyModule_Create(&embedded_ext);
100}
101
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000102/*****************************************************
103 * Test forcing a particular IO encoding
104 *****************************************************/
105
106static void check_stdio_details(const char *encoding, const char * errors)
107{
108 /* Output info for the test case to check */
109 if (encoding) {
110 printf("Expected encoding: %s\n", encoding);
111 } else {
112 printf("Expected encoding: default\n");
113 }
114 if (errors) {
115 printf("Expected errors: %s\n", errors);
116 } else {
117 printf("Expected errors: default\n");
118 }
119 fflush(stdout);
120 /* Force the given IO encoding */
121 Py_SetStandardStreamEncoding(encoding, errors);
122 _testembed_Py_Initialize();
123 PyRun_SimpleString(
124 "import sys;"
125 "print('stdin: {0.encoding}:{0.errors}'.format(sys.stdin));"
126 "print('stdout: {0.encoding}:{0.errors}'.format(sys.stdout));"
127 "print('stderr: {0.encoding}:{0.errors}'.format(sys.stderr));"
128 "sys.stdout.flush()"
129 );
130 Py_Finalize();
131}
132
Steve Dowerea74f0c2017-01-01 20:25:03 -0800133static int test_forced_io_encoding(void)
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000134{
135 /* Check various combinations */
136 printf("--- Use defaults ---\n");
137 check_stdio_details(NULL, NULL);
138 printf("--- Set errors only ---\n");
Victor Stinnerb2bef622014-03-18 02:38:12 +0100139 check_stdio_details(NULL, "ignore");
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000140 printf("--- Set encoding only ---\n");
Victor Stinner9e4994d2018-08-28 23:26:33 +0200141 check_stdio_details("iso8859-1", NULL);
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000142 printf("--- Set encoding and errors ---\n");
Victor Stinner9e4994d2018-08-28 23:26:33 +0200143 check_stdio_details("iso8859-1", "replace");
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000144
145 /* Check calling after initialization fails */
146 Py_Initialize();
147
148 if (Py_SetStandardStreamEncoding(NULL, NULL) == 0) {
149 printf("Unexpected success calling Py_SetStandardStreamEncoding");
150 }
151 Py_Finalize();
Steve Dowerea74f0c2017-01-01 20:25:03 -0800152 return 0;
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000153}
154
Victor Stinner9e87e772017-11-24 12:09:24 +0100155/*********************************************************
156 * Test parts of the C-API that work before initialization
157 *********************************************************/
158
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000159/* The pre-initialization tests tend to break by segfaulting, so explicitly
160 * flushed progress messages make the broken API easier to find when they fail.
161 */
162#define _Py_EMBED_PREINIT_CHECK(msg) \
163 do {printf(msg); fflush(stdout);} while (0);
164
Victor Stinner9e87e772017-11-24 12:09:24 +0100165static int test_pre_initialization_api(void)
166{
Victor Stinnera9df6512019-03-05 23:31:54 +0100167 /* the test doesn't support custom memory allocators */
168 putenv("PYTHONMALLOC=");
169
Nick Coghlan42746092017-11-26 14:19:13 +1000170 /* Leading "./" ensures getpath.c can still find the standard library */
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000171 _Py_EMBED_PREINIT_CHECK("Checking Py_DecodeLocale\n");
Nick Coghlan42746092017-11-26 14:19:13 +1000172 wchar_t *program = Py_DecodeLocale("./spam", NULL);
Victor Stinner9e87e772017-11-24 12:09:24 +0100173 if (program == NULL) {
174 fprintf(stderr, "Fatal error: cannot decode program name\n");
175 return 1;
176 }
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000177 _Py_EMBED_PREINIT_CHECK("Checking Py_SetProgramName\n");
Victor Stinner9e87e772017-11-24 12:09:24 +0100178 Py_SetProgramName(program);
179
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000180 _Py_EMBED_PREINIT_CHECK("Initializing interpreter\n");
Victor Stinner9e87e772017-11-24 12:09:24 +0100181 Py_Initialize();
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000182 _Py_EMBED_PREINIT_CHECK("Check sys module contents\n");
183 PyRun_SimpleString("import sys; "
184 "print('sys.executable:', sys.executable)");
185 _Py_EMBED_PREINIT_CHECK("Finalizing interpreter\n");
Victor Stinner9e87e772017-11-24 12:09:24 +0100186 Py_Finalize();
187
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000188 _Py_EMBED_PREINIT_CHECK("Freeing memory allocated by Py_DecodeLocale\n");
Victor Stinner9e87e772017-11-24 12:09:24 +0100189 PyMem_RawFree(program);
190 return 0;
191}
192
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000193
194/* bpo-33042: Ensure embedding apps can predefine sys module options */
195static int test_pre_initialization_sys_options(void)
196{
Nick Coghlan69f5c732018-03-30 15:36:42 +1000197 /* We allocate a couple of the options dynamically, and then delete
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000198 * them before calling Py_Initialize. This ensures the interpreter isn't
199 * relying on the caller to keep the passed in strings alive.
200 */
Nick Coghlan69f5c732018-03-30 15:36:42 +1000201 const wchar_t *static_warnoption = L"once";
202 const wchar_t *static_xoption = L"also_not_an_option=2";
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000203 size_t warnoption_len = wcslen(static_warnoption);
204 size_t xoption_len = wcslen(static_xoption);
Nick Coghlan69f5c732018-03-30 15:36:42 +1000205 wchar_t *dynamic_once_warnoption = \
206 (wchar_t *) calloc(warnoption_len+1, sizeof(wchar_t));
207 wchar_t *dynamic_xoption = \
208 (wchar_t *) calloc(xoption_len+1, sizeof(wchar_t));
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000209 wcsncpy(dynamic_once_warnoption, static_warnoption, warnoption_len+1);
210 wcsncpy(dynamic_xoption, static_xoption, xoption_len+1);
211
212 _Py_EMBED_PREINIT_CHECK("Checking PySys_AddWarnOption\n");
213 PySys_AddWarnOption(L"default");
214 _Py_EMBED_PREINIT_CHECK("Checking PySys_ResetWarnOptions\n");
215 PySys_ResetWarnOptions();
216 _Py_EMBED_PREINIT_CHECK("Checking PySys_AddWarnOption linked list\n");
217 PySys_AddWarnOption(dynamic_once_warnoption);
218 PySys_AddWarnOption(L"module");
219 PySys_AddWarnOption(L"default");
220 _Py_EMBED_PREINIT_CHECK("Checking PySys_AddXOption\n");
221 PySys_AddXOption(L"not_an_option=1");
222 PySys_AddXOption(dynamic_xoption);
223
224 /* Delete the dynamic options early */
225 free(dynamic_once_warnoption);
226 dynamic_once_warnoption = NULL;
227 free(dynamic_xoption);
228 dynamic_xoption = NULL;
229
230 _Py_EMBED_PREINIT_CHECK("Initializing interpreter\n");
231 _testembed_Py_Initialize();
232 _Py_EMBED_PREINIT_CHECK("Check sys module contents\n");
233 PyRun_SimpleString("import sys; "
234 "print('sys.warnoptions:', sys.warnoptions); "
235 "print('sys._xoptions:', sys._xoptions); "
236 "warnings = sys.modules['warnings']; "
237 "latest_filters = [f[0] for f in warnings.filters[:3]]; "
238 "print('warnings.filters[:3]:', latest_filters)");
239 _Py_EMBED_PREINIT_CHECK("Finalizing interpreter\n");
240 Py_Finalize();
241
242 return 0;
243}
244
245
246/* bpo-20891: Avoid race condition when initialising the GIL */
Victor Stinnerb4d1e1f2017-11-30 22:05:00 +0100247static void bpo20891_thread(void *lockp)
248{
249 PyThread_type_lock lock = *((PyThread_type_lock*)lockp);
250
251 PyGILState_STATE state = PyGILState_Ensure();
252 if (!PyGILState_Check()) {
253 fprintf(stderr, "PyGILState_Check failed!");
254 abort();
255 }
256
257 PyGILState_Release(state);
258
259 PyThread_release_lock(lock);
260
261 PyThread_exit_thread();
262}
263
264static int test_bpo20891(void)
265{
Victor Stinnera9df6512019-03-05 23:31:54 +0100266 /* the test doesn't support custom memory allocators */
267 putenv("PYTHONMALLOC=");
268
Victor Stinner3225b9f2020-03-09 20:56:57 +0100269 /* bpo-20891: Calling PyGILState_Ensure in a non-Python thread must not
270 crash. */
Victor Stinnerb4d1e1f2017-11-30 22:05:00 +0100271 PyThread_type_lock lock = PyThread_allocate_lock();
272 if (!lock) {
273 fprintf(stderr, "PyThread_allocate_lock failed!");
274 return 1;
275 }
276
277 _testembed_Py_Initialize();
278
279 unsigned long thrd = PyThread_start_new_thread(bpo20891_thread, &lock);
280 if (thrd == PYTHREAD_INVALID_THREAD_ID) {
281 fprintf(stderr, "PyThread_start_new_thread failed!");
282 return 1;
283 }
284 PyThread_acquire_lock(lock, WAIT_LOCK);
285
286 Py_BEGIN_ALLOW_THREADS
287 /* wait until the thread exit */
288 PyThread_acquire_lock(lock, WAIT_LOCK);
289 Py_END_ALLOW_THREADS
290
291 PyThread_free_lock(lock);
292
293 return 0;
294}
295
Victor Stinner209abf72018-06-22 19:14:51 +0200296static int test_initialize_twice(void)
297{
298 _testembed_Py_Initialize();
299
300 /* bpo-33932: Calling Py_Initialize() twice should do nothing
301 * (and not crash!). */
302 Py_Initialize();
303
304 Py_Finalize();
305
306 return 0;
307}
308
Victor Stinnerfb47bca2018-07-20 17:34:23 +0200309static int test_initialize_pymain(void)
310{
311 wchar_t *argv[] = {L"PYTHON", L"-c",
Victor Stinnercab5d072019-05-17 19:01:14 +0200312 (L"import sys; "
313 L"print(f'Py_Main() after Py_Initialize: "
314 L"sys.argv={sys.argv}')"),
Victor Stinnerfb47bca2018-07-20 17:34:23 +0200315 L"arg2"};
316 _testembed_Py_Initialize();
317
318 /* bpo-34008: Calling Py_Main() after Py_Initialize() must not crash */
319 Py_Main(Py_ARRAY_LENGTH(argv), argv);
320
321 Py_Finalize();
322
323 return 0;
324}
325
Victor Stinner9e87e772017-11-24 12:09:24 +0100326
Victor Stinner00b137c2018-11-13 19:59:26 +0100327static void
328dump_config(void)
329{
Victor Stinner23bace22019-04-18 11:37:26 +0200330 (void) PyRun_SimpleStringFlags(
331 "import _testinternalcapi, json; "
332 "print(json.dumps(_testinternalcapi.get_configs()))",
333 0);
Victor Stinner00b137c2018-11-13 19:59:26 +0100334}
335
336
Victor Stinner022be022019-05-22 23:58:50 +0200337static int test_init_initialize_config(void)
Victor Stinner56b29b62018-07-26 18:57:56 +0200338{
339 _testembed_Py_Initialize();
340 dump_config();
341 Py_Finalize();
342 return 0;
343}
344
345
Victor Stinner67310022019-07-01 19:52:45 +0200346static void config_set_string(PyConfig *config, wchar_t **config_str, const wchar_t *str)
347{
348 PyStatus status = PyConfig_SetString(config, config_str, str);
349 if (PyStatus_Exception(status)) {
350 PyConfig_Clear(config);
351 Py_ExitStatusException(status);
352 }
353}
354
355
356static void config_set_argv(PyConfig *config, Py_ssize_t argc, wchar_t * const *argv)
357{
358 PyStatus status = PyConfig_SetArgv(config, argc, argv);
359 if (PyStatus_Exception(status)) {
360 PyConfig_Clear(config);
361 Py_ExitStatusException(status);
362 }
363}
364
365
366static void
367config_set_wide_string_list(PyConfig *config, PyWideStringList *list,
368 Py_ssize_t length, wchar_t **items)
369{
370 PyStatus status = PyConfig_SetWideStringList(config, list, length, items);
371 if (PyStatus_Exception(status)) {
372 PyConfig_Clear(config);
373 Py_ExitStatusException(status);
374 }
375}
376
377
378static void config_set_program_name(PyConfig *config)
379{
Victor Stinnerbb6bf7d2019-09-24 18:21:02 +0200380 const wchar_t *program_name = PROGRAM_NAME;
Victor Stinner67310022019-07-01 19:52:45 +0200381 config_set_string(config, &config->program_name, program_name);
382}
383
384
385static void init_from_config_clear(PyConfig *config)
386{
387 PyStatus status = Py_InitializeFromConfig(config);
388 PyConfig_Clear(config);
389 if (PyStatus_Exception(status)) {
390 Py_ExitStatusException(status);
391 }
392}
393
394
Victor Stinner022be022019-05-22 23:58:50 +0200395static int check_init_compat_config(int preinit)
396{
Victor Stinner331a6a52019-05-27 16:39:22 +0200397 PyStatus status;
Victor Stinner022be022019-05-22 23:58:50 +0200398
399 if (preinit) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200400 PyPreConfig preconfig;
Victor Stinner3c30a762019-10-01 10:56:37 +0200401 _PyPreConfig_InitCompatConfig(&preconfig);
Victor Stinner022be022019-05-22 23:58:50 +0200402
Victor Stinner331a6a52019-05-27 16:39:22 +0200403 status = Py_PreInitialize(&preconfig);
404 if (PyStatus_Exception(status)) {
405 Py_ExitStatusException(status);
Victor Stinner022be022019-05-22 23:58:50 +0200406 }
407 }
408
Victor Stinner331a6a52019-05-27 16:39:22 +0200409 PyConfig config;
Victor Stinner8462a492019-10-01 12:06:16 +0200410 _PyConfig_InitCompatConfig(&config);
Victor Stinner441b10c2019-09-28 04:28:35 +0200411
Victor Stinner67310022019-07-01 19:52:45 +0200412 config_set_program_name(&config);
413 init_from_config_clear(&config);
Victor Stinner022be022019-05-22 23:58:50 +0200414
415 dump_config();
416 Py_Finalize();
417 return 0;
418}
419
420
421static int test_preinit_compat_config(void)
422{
423 return check_init_compat_config(1);
424}
425
426
427static int test_init_compat_config(void)
428{
429 return check_init_compat_config(0);
430}
431
432
Victor Stinner56b29b62018-07-26 18:57:56 +0200433static int test_init_global_config(void)
434{
435 /* FIXME: test Py_IgnoreEnvironmentFlag */
436
437 putenv("PYTHONUTF8=0");
438 Py_UTF8Mode = 1;
439
440 /* Test initialization from global configuration variables (Py_xxx) */
441 Py_SetProgramName(L"./globalvar");
442
443 /* Py_IsolatedFlag is not tested */
444 Py_NoSiteFlag = 1;
445 Py_BytesWarningFlag = 1;
446
447 putenv("PYTHONINSPECT=");
448 Py_InspectFlag = 1;
449
450 putenv("PYTHONOPTIMIZE=0");
451 Py_InteractiveFlag = 1;
452
453 putenv("PYTHONDEBUG=0");
454 Py_OptimizeFlag = 2;
455
456 /* Py_DebugFlag is not tested */
457
458 putenv("PYTHONDONTWRITEBYTECODE=");
459 Py_DontWriteBytecodeFlag = 1;
460
461 putenv("PYTHONVERBOSE=0");
462 Py_VerboseFlag = 1;
463
464 Py_QuietFlag = 1;
465 Py_NoUserSiteDirectory = 1;
466
467 putenv("PYTHONUNBUFFERED=");
468 Py_UnbufferedStdioFlag = 1;
469
Victor Stinner54b43bb2019-05-16 18:30:15 +0200470 Py_FrozenFlag = 1;
471
Victor Stinner56b29b62018-07-26 18:57:56 +0200472 /* FIXME: test Py_LegacyWindowsFSEncodingFlag */
473 /* FIXME: test Py_LegacyWindowsStdioFlag */
474
Victor Stinner56b29b62018-07-26 18:57:56 +0200475 Py_Initialize();
476 dump_config();
477 Py_Finalize();
478 return 0;
479}
480
481
482static int test_init_from_config(void)
483{
Victor Stinner331a6a52019-05-27 16:39:22 +0200484 PyPreConfig preconfig;
Victor Stinner3c30a762019-10-01 10:56:37 +0200485 _PyPreConfig_InitCompatConfig(&preconfig);
Victor Stinner20004952019-03-26 02:31:11 +0100486
487 putenv("PYTHONMALLOC=malloc_debug");
Victor Stinnerb16b4e42019-05-17 15:20:52 +0200488 preconfig.allocator = PYMEM_ALLOCATOR_MALLOC;
Victor Stinner20004952019-03-26 02:31:11 +0100489
490 putenv("PYTHONUTF8=0");
491 Py_UTF8Mode = 0;
492 preconfig.utf8_mode = 1;
493
Victor Stinner3c30a762019-10-01 10:56:37 +0200494 PyStatus status = Py_PreInitialize(&preconfig);
Victor Stinner331a6a52019-05-27 16:39:22 +0200495 if (PyStatus_Exception(status)) {
496 Py_ExitStatusException(status);
Victor Stinner20004952019-03-26 02:31:11 +0100497 }
498
Victor Stinner331a6a52019-05-27 16:39:22 +0200499 PyConfig config;
Victor Stinner8462a492019-10-01 12:06:16 +0200500 _PyConfig_InitCompatConfig(&config);
Victor Stinner441b10c2019-09-28 04:28:35 +0200501
Victor Stinner56b29b62018-07-26 18:57:56 +0200502 config.install_signal_handlers = 0;
503
504 /* FIXME: test use_environment */
505
506 putenv("PYTHONHASHSEED=42");
507 config.use_hash_seed = 1;
508 config.hash_seed = 123;
509
Victor Stinnerbab0db62019-05-18 03:21:27 +0200510 /* dev_mode=1 is tested in test_init_dev_mode() */
Victor Stinner56b29b62018-07-26 18:57:56 +0200511
512 putenv("PYTHONFAULTHANDLER=");
513 config.faulthandler = 1;
514
515 putenv("PYTHONTRACEMALLOC=0");
516 config.tracemalloc = 2;
517
518 putenv("PYTHONPROFILEIMPORTTIME=0");
519 config.import_time = 1;
520
521 config.show_ref_count = 1;
Victor Stinner56b29b62018-07-26 18:57:56 +0200522 /* FIXME: test dump_refs: bpo-34223 */
523
524 putenv("PYTHONMALLOCSTATS=0");
525 config.malloc_stats = 1;
526
Victor Stinner56b29b62018-07-26 18:57:56 +0200527 putenv("PYTHONPYCACHEPREFIX=env_pycache_prefix");
Victor Stinner67310022019-07-01 19:52:45 +0200528 config_set_string(&config, &config.pycache_prefix, L"conf_pycache_prefix");
Victor Stinner56b29b62018-07-26 18:57:56 +0200529
530 Py_SetProgramName(L"./globalvar");
Victor Stinner67310022019-07-01 19:52:45 +0200531 config_set_string(&config, &config.program_name, L"./conf_program_name");
Victor Stinner56b29b62018-07-26 18:57:56 +0200532
Victor Stinner67310022019-07-01 19:52:45 +0200533 wchar_t* argv[] = {
Victor Stinner2f549082019-03-29 15:13:46 +0100534 L"python3",
Victor Stinner67310022019-07-01 19:52:45 +0200535 L"-W",
536 L"cmdline_warnoption",
537 L"-X",
538 L"cmdline_xoption",
Victor Stinner01de89c2018-11-14 17:39:45 +0100539 L"-c",
540 L"pass",
Victor Stinner2f549082019-03-29 15:13:46 +0100541 L"arg2",
Victor Stinner01de89c2018-11-14 17:39:45 +0100542 };
Victor Stinner67310022019-07-01 19:52:45 +0200543 config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
Victor Stinnercab5d072019-05-17 19:01:14 +0200544 config.parse_argv = 1;
Victor Stinner01de89c2018-11-14 17:39:45 +0100545
Victor Stinner67310022019-07-01 19:52:45 +0200546 wchar_t* xoptions[3] = {
547 L"config_xoption1=3",
548 L"config_xoption2=",
549 L"config_xoption3",
Victor Stinner01de89c2018-11-14 17:39:45 +0100550 };
Victor Stinner67310022019-07-01 19:52:45 +0200551 config_set_wide_string_list(&config, &config.xoptions,
552 Py_ARRAY_LENGTH(xoptions), xoptions);
Victor Stinner01de89c2018-11-14 17:39:45 +0100553
Victor Stinner67310022019-07-01 19:52:45 +0200554 wchar_t* warnoptions[1] = {
555 L"config_warnoption",
Victor Stinner01de89c2018-11-14 17:39:45 +0100556 };
Victor Stinner67310022019-07-01 19:52:45 +0200557 config_set_wide_string_list(&config, &config.warnoptions,
558 Py_ARRAY_LENGTH(warnoptions), warnoptions);
Victor Stinner01de89c2018-11-14 17:39:45 +0100559
Victor Stinner331a6a52019-05-27 16:39:22 +0200560 /* FIXME: test pythonpath_env */
Victor Stinner56b29b62018-07-26 18:57:56 +0200561 /* FIXME: test home */
562 /* FIXME: test path config: module_search_path .. dll_path */
563
Sandro Mani8f023a22020-06-08 17:28:11 +0200564 putenv("PYTHONPLATLIBDIR=env_platlibdir");
565 status = PyConfig_SetBytesString(&config, &config.platlibdir, "my_platlibdir");
566 if (PyStatus_Exception(status)) {
567 PyConfig_Clear(&config);
568 Py_ExitStatusException(status);
569 }
570
Victor Stinner56b29b62018-07-26 18:57:56 +0200571 putenv("PYTHONVERBOSE=0");
572 Py_VerboseFlag = 0;
573 config.verbose = 1;
574
575 Py_NoSiteFlag = 0;
576 config.site_import = 0;
577
578 Py_BytesWarningFlag = 0;
579 config.bytes_warning = 1;
580
581 putenv("PYTHONINSPECT=");
582 Py_InspectFlag = 0;
583 config.inspect = 1;
584
585 Py_InteractiveFlag = 0;
586 config.interactive = 1;
587
588 putenv("PYTHONOPTIMIZE=0");
589 Py_OptimizeFlag = 1;
590 config.optimization_level = 2;
591
Victor Stinner98512272018-08-01 03:07:00 +0200592 /* FIXME: test parser_debug */
Victor Stinner56b29b62018-07-26 18:57:56 +0200593
594 putenv("PYTHONDONTWRITEBYTECODE=");
595 Py_DontWriteBytecodeFlag = 0;
596 config.write_bytecode = 0;
597
598 Py_QuietFlag = 0;
599 config.quiet = 1;
600
Victor Stinnercab5d072019-05-17 19:01:14 +0200601 config.configure_c_stdio = 1;
Victor Stinner54b43bb2019-05-16 18:30:15 +0200602
Victor Stinner56b29b62018-07-26 18:57:56 +0200603 putenv("PYTHONUNBUFFERED=");
604 Py_UnbufferedStdioFlag = 0;
Victor Stinner98512272018-08-01 03:07:00 +0200605 config.buffered_stdio = 0;
Victor Stinner56b29b62018-07-26 18:57:56 +0200606
Victor Stinnerdfe0dc72018-08-29 11:47:29 +0200607 putenv("PYTHONIOENCODING=cp424");
608 Py_SetStandardStreamEncoding("ascii", "ignore");
Victor Stinner01de89c2018-11-14 17:39:45 +0100609#ifdef MS_WINDOWS
610 /* Py_SetStandardStreamEncoding() sets Py_LegacyWindowsStdioFlag to 1.
611 Force it to 0 through the config. */
612 config.legacy_windows_stdio = 0;
613#endif
Victor Stinner67310022019-07-01 19:52:45 +0200614 config_set_string(&config, &config.stdio_encoding, L"iso8859-1");
615 config_set_string(&config, &config.stdio_errors, L"replace");
Victor Stinnerdfe0dc72018-08-29 11:47:29 +0200616
Victor Stinner56b29b62018-07-26 18:57:56 +0200617 putenv("PYTHONNOUSERSITE=");
618 Py_NoUserSiteDirectory = 0;
619 config.user_site_directory = 0;
620
Victor Stinner67310022019-07-01 19:52:45 +0200621 config_set_string(&config, &config.check_hash_pycs_mode, L"always");
Victor Stinner56b29b62018-07-26 18:57:56 +0200622
Victor Stinner54b43bb2019-05-16 18:30:15 +0200623 Py_FrozenFlag = 0;
624 config.pathconfig_warnings = 0;
625
Victor Stinner252346a2020-05-01 11:33:44 +0200626 config._isolated_interpreter = 1;
627
Victor Stinner67310022019-07-01 19:52:45 +0200628 init_from_config_clear(&config);
629
Victor Stinner56b29b62018-07-26 18:57:56 +0200630 dump_config();
631 Py_Finalize();
632 return 0;
633}
634
635
Victor Stinnerbab0db62019-05-18 03:21:27 +0200636static int check_init_parse_argv(int parse_argv)
Victor Stinnerae239f62019-05-16 17:02:56 +0200637{
Victor Stinner331a6a52019-05-27 16:39:22 +0200638 PyConfig config;
Victor Stinner8462a492019-10-01 12:06:16 +0200639 PyConfig_InitPythonConfig(&config);
Victor Stinnerae239f62019-05-16 17:02:56 +0200640
Victor Stinner67310022019-07-01 19:52:45 +0200641 config.parse_argv = parse_argv;
642
643 wchar_t* argv[] = {
Victor Stinnercab5d072019-05-17 19:01:14 +0200644 L"./argv0",
645 L"-E",
Victor Stinnerae239f62019-05-16 17:02:56 +0200646 L"-c",
Victor Stinnercab5d072019-05-17 19:01:14 +0200647 L"pass",
Victor Stinnerae239f62019-05-16 17:02:56 +0200648 L"arg1",
Victor Stinnercab5d072019-05-17 19:01:14 +0200649 L"-v",
650 L"arg3",
Victor Stinnerae239f62019-05-16 17:02:56 +0200651 };
Victor Stinner67310022019-07-01 19:52:45 +0200652 config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
653 init_from_config_clear(&config);
Victor Stinnerae239f62019-05-16 17:02:56 +0200654
Victor Stinnerae239f62019-05-16 17:02:56 +0200655 dump_config();
656 Py_Finalize();
657 return 0;
658}
659
660
Victor Stinnerbab0db62019-05-18 03:21:27 +0200661static int test_init_parse_argv(void)
Victor Stinnercab5d072019-05-17 19:01:14 +0200662{
Victor Stinnerbab0db62019-05-18 03:21:27 +0200663 return check_init_parse_argv(1);
Victor Stinnercab5d072019-05-17 19:01:14 +0200664}
665
666
Victor Stinnerbab0db62019-05-18 03:21:27 +0200667static int test_init_dont_parse_argv(void)
Victor Stinnercab5d072019-05-17 19:01:14 +0200668{
Victor Stinnerbab0db62019-05-18 03:21:27 +0200669 return check_init_parse_argv(0);
Victor Stinnercab5d072019-05-17 19:01:14 +0200670}
671
672
Victor Stinner425717f2019-05-20 16:38:48 +0200673static void set_most_env_vars(void)
Victor Stinner56b29b62018-07-26 18:57:56 +0200674{
675 putenv("PYTHONHASHSEED=42");
Victor Stinner25d13f32019-03-06 12:51:53 +0100676 putenv("PYTHONMALLOC=malloc");
Victor Stinner56b29b62018-07-26 18:57:56 +0200677 putenv("PYTHONTRACEMALLOC=2");
678 putenv("PYTHONPROFILEIMPORTTIME=1");
679 putenv("PYTHONMALLOCSTATS=1");
680 putenv("PYTHONUTF8=1");
681 putenv("PYTHONVERBOSE=1");
682 putenv("PYTHONINSPECT=1");
683 putenv("PYTHONOPTIMIZE=2");
684 putenv("PYTHONDONTWRITEBYTECODE=1");
685 putenv("PYTHONUNBUFFERED=1");
686 putenv("PYTHONPYCACHEPREFIX=env_pycache_prefix");
687 putenv("PYTHONNOUSERSITE=1");
688 putenv("PYTHONFAULTHANDLER=1");
Victor Stinnerdfe0dc72018-08-29 11:47:29 +0200689 putenv("PYTHONIOENCODING=iso8859-1:replace");
Sandro Mani8f023a22020-06-08 17:28:11 +0200690 putenv("PYTHONPLATLIBDIR=env_platlibdir");
Victor Stinner425717f2019-05-20 16:38:48 +0200691}
692
693
694static void set_all_env_vars(void)
695{
696 set_most_env_vars();
697
698 putenv("PYTHONWARNINGS=EnvVar");
699 putenv("PYTHONPATH=/my/path");
Victor Stinner56b29b62018-07-26 18:57:56 +0200700}
701
702
Victor Stinner20e1e252019-05-23 04:12:27 +0200703static int test_init_compat_env(void)
Victor Stinner56b29b62018-07-26 18:57:56 +0200704{
705 /* Test initialization from environment variables */
706 Py_IgnoreEnvironmentFlag = 0;
Victor Stinner6d1c4672019-05-20 11:02:00 +0200707 set_all_env_vars();
Victor Stinner56b29b62018-07-26 18:57:56 +0200708 _testembed_Py_Initialize();
709 dump_config();
710 Py_Finalize();
711 return 0;
712}
713
714
Victor Stinner20e1e252019-05-23 04:12:27 +0200715static int test_init_python_env(void)
716{
Victor Stinner20e1e252019-05-23 04:12:27 +0200717 set_all_env_vars();
718
Victor Stinner331a6a52019-05-27 16:39:22 +0200719 PyConfig config;
Victor Stinner8462a492019-10-01 12:06:16 +0200720 PyConfig_InitPythonConfig(&config);
Victor Stinner20e1e252019-05-23 04:12:27 +0200721
Victor Stinner67310022019-07-01 19:52:45 +0200722 config_set_program_name(&config);
723 init_from_config_clear(&config);
724
Victor Stinner20e1e252019-05-23 04:12:27 +0200725 dump_config();
726 Py_Finalize();
727 return 0;
728}
729
730
Victor Stinner6d1c4672019-05-20 11:02:00 +0200731static void set_all_env_vars_dev_mode(void)
Victor Stinner25d13f32019-03-06 12:51:53 +0100732{
Victor Stinner25d13f32019-03-06 12:51:53 +0100733 putenv("PYTHONMALLOC=");
734 putenv("PYTHONFAULTHANDLER=");
735 putenv("PYTHONDEVMODE=1");
736}
737
738
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100739static int test_init_env_dev_mode(void)
740{
741 /* Test initialization from environment variables */
742 Py_IgnoreEnvironmentFlag = 0;
Victor Stinner6d1c4672019-05-20 11:02:00 +0200743 set_all_env_vars_dev_mode();
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100744 _testembed_Py_Initialize();
745 dump_config();
746 Py_Finalize();
747 return 0;
748}
749
750
Victor Stinner25d13f32019-03-06 12:51:53 +0100751static int test_init_env_dev_mode_alloc(void)
752{
753 /* Test initialization from environment variables */
754 Py_IgnoreEnvironmentFlag = 0;
Victor Stinner6d1c4672019-05-20 11:02:00 +0200755 set_all_env_vars_dev_mode();
Victor Stinner25d13f32019-03-06 12:51:53 +0100756 putenv("PYTHONMALLOC=malloc");
757 _testembed_Py_Initialize();
758 dump_config();
759 Py_Finalize();
760 return 0;
761}
762
763
Victor Stinnerbab0db62019-05-18 03:21:27 +0200764static int test_init_isolated_flag(void)
Victor Stinner56b29b62018-07-26 18:57:56 +0200765{
Victor Stinner331a6a52019-05-27 16:39:22 +0200766 /* Test PyConfig.isolated=1 */
767 PyConfig config;
Victor Stinner8462a492019-10-01 12:06:16 +0200768 PyConfig_InitPythonConfig(&config);
Victor Stinner56b29b62018-07-26 18:57:56 +0200769
Victor Stinnercad1f742019-03-05 02:01:27 +0100770 Py_IsolatedFlag = 0;
Victor Stinner20004952019-03-26 02:31:11 +0100771 config.isolated = 1;
Victor Stinnercad1f742019-03-05 02:01:27 +0100772
Victor Stinner67310022019-07-01 19:52:45 +0200773 config_set_program_name(&config);
Victor Stinnerbab0db62019-05-18 03:21:27 +0200774 set_all_env_vars();
Victor Stinner67310022019-07-01 19:52:45 +0200775 init_from_config_clear(&config);
776
Victor Stinner56b29b62018-07-26 18:57:56 +0200777 dump_config();
778 Py_Finalize();
779 return 0;
780}
781
782
Victor Stinner331a6a52019-05-27 16:39:22 +0200783/* PyPreConfig.isolated=1, PyConfig.isolated=0 */
Victor Stinner6da20a42019-03-27 00:26:18 +0100784static int test_preinit_isolated1(void)
785{
Victor Stinner331a6a52019-05-27 16:39:22 +0200786 PyPreConfig preconfig;
Victor Stinner3c30a762019-10-01 10:56:37 +0200787 _PyPreConfig_InitCompatConfig(&preconfig);
Victor Stinner441b10c2019-09-28 04:28:35 +0200788
Victor Stinner6da20a42019-03-27 00:26:18 +0100789 preconfig.isolated = 1;
790
Victor Stinner3c30a762019-10-01 10:56:37 +0200791 PyStatus status = Py_PreInitialize(&preconfig);
Victor Stinner331a6a52019-05-27 16:39:22 +0200792 if (PyStatus_Exception(status)) {
793 Py_ExitStatusException(status);
Victor Stinner6da20a42019-03-27 00:26:18 +0100794 }
795
Victor Stinner331a6a52019-05-27 16:39:22 +0200796 PyConfig config;
Victor Stinner8462a492019-10-01 12:06:16 +0200797 _PyConfig_InitCompatConfig(&config);
Victor Stinner441b10c2019-09-28 04:28:35 +0200798
Victor Stinner67310022019-07-01 19:52:45 +0200799 config_set_program_name(&config);
Victor Stinnerbab0db62019-05-18 03:21:27 +0200800 set_all_env_vars();
Victor Stinner67310022019-07-01 19:52:45 +0200801 init_from_config_clear(&config);
802
Victor Stinner6da20a42019-03-27 00:26:18 +0100803 dump_config();
804 Py_Finalize();
805 return 0;
806}
807
808
Victor Stinner331a6a52019-05-27 16:39:22 +0200809/* PyPreConfig.isolated=0, PyConfig.isolated=1 */
Victor Stinner6da20a42019-03-27 00:26:18 +0100810static int test_preinit_isolated2(void)
811{
Victor Stinner331a6a52019-05-27 16:39:22 +0200812 PyPreConfig preconfig;
Victor Stinner3c30a762019-10-01 10:56:37 +0200813 _PyPreConfig_InitCompatConfig(&preconfig);
Victor Stinner441b10c2019-09-28 04:28:35 +0200814
Victor Stinner6da20a42019-03-27 00:26:18 +0100815 preconfig.isolated = 0;
816
Victor Stinner3c30a762019-10-01 10:56:37 +0200817 PyStatus status = Py_PreInitialize(&preconfig);
Victor Stinner331a6a52019-05-27 16:39:22 +0200818 if (PyStatus_Exception(status)) {
819 Py_ExitStatusException(status);
Victor Stinner6da20a42019-03-27 00:26:18 +0100820 }
821
Victor Stinner331a6a52019-05-27 16:39:22 +0200822 /* Test PyConfig.isolated=1 */
823 PyConfig config;
Victor Stinner8462a492019-10-01 12:06:16 +0200824 _PyConfig_InitCompatConfig(&config);
Victor Stinner6da20a42019-03-27 00:26:18 +0100825
826 Py_IsolatedFlag = 0;
827 config.isolated = 1;
828
Victor Stinner67310022019-07-01 19:52:45 +0200829 config_set_program_name(&config);
Victor Stinnerbab0db62019-05-18 03:21:27 +0200830 set_all_env_vars();
Victor Stinner67310022019-07-01 19:52:45 +0200831 init_from_config_clear(&config);
832
Victor Stinner6da20a42019-03-27 00:26:18 +0100833 dump_config();
834 Py_Finalize();
835 return 0;
836}
837
838
Victor Stinner6d1c4672019-05-20 11:02:00 +0200839static int test_preinit_dont_parse_argv(void)
840{
Victor Stinner331a6a52019-05-27 16:39:22 +0200841 PyPreConfig preconfig;
Victor Stinner3c30a762019-10-01 10:56:37 +0200842 PyPreConfig_InitIsolatedConfig(&preconfig);
Victor Stinner6d1c4672019-05-20 11:02:00 +0200843
844 preconfig.isolated = 0;
845
846 /* -X dev must be ignored by isolated preconfiguration */
847 wchar_t *argv[] = {L"python3",
848 L"-E",
849 L"-I",
850 L"-X", L"dev",
851 L"-X", L"utf8",
852 L"script.py"};
Victor Stinner3c30a762019-10-01 10:56:37 +0200853 PyStatus status = Py_PreInitializeFromArgs(&preconfig,
854 Py_ARRAY_LENGTH(argv), argv);
Victor Stinner331a6a52019-05-27 16:39:22 +0200855 if (PyStatus_Exception(status)) {
Victor Stinner67310022019-07-01 19:52:45 +0200856 Py_ExitStatusException(status);
Victor Stinner6d1c4672019-05-20 11:02:00 +0200857 }
858
Victor Stinner331a6a52019-05-27 16:39:22 +0200859 PyConfig config;
Victor Stinner8462a492019-10-01 12:06:16 +0200860 PyConfig_InitIsolatedConfig(&config);
Victor Stinner6d1c4672019-05-20 11:02:00 +0200861
862 config.isolated = 0;
863
864 /* Pre-initialize implicitly using argv: make sure that -X dev
865 is used to configure the allocation in preinitialization */
Victor Stinner67310022019-07-01 19:52:45 +0200866 config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
867 config_set_program_name(&config);
868 init_from_config_clear(&config);
Victor Stinner6d1c4672019-05-20 11:02:00 +0200869
870 dump_config();
871 Py_Finalize();
872 return 0;
Victor Stinner6d1c4672019-05-20 11:02:00 +0200873}
874
875
876static int test_preinit_parse_argv(void)
877{
Victor Stinner331a6a52019-05-27 16:39:22 +0200878 PyConfig config;
Victor Stinner8462a492019-10-01 12:06:16 +0200879 PyConfig_InitPythonConfig(&config);
Victor Stinner6d1c4672019-05-20 11:02:00 +0200880
881 /* Pre-initialize implicitly using argv: make sure that -X dev
882 is used to configure the allocation in preinitialization */
883 wchar_t *argv[] = {L"python3", L"-X", L"dev", L"script.py"};
Victor Stinner67310022019-07-01 19:52:45 +0200884 config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
885 config_set_program_name(&config);
886 init_from_config_clear(&config);
Victor Stinner6d1c4672019-05-20 11:02:00 +0200887
888 dump_config();
889 Py_Finalize();
890 return 0;
Victor Stinner6d1c4672019-05-20 11:02:00 +0200891}
892
893
894
895
Victor Stinnerbab0db62019-05-18 03:21:27 +0200896static void set_all_global_config_variables(void)
897{
898 Py_IsolatedFlag = 0;
899 Py_IgnoreEnvironmentFlag = 0;
900 Py_BytesWarningFlag = 2;
901 Py_InspectFlag = 1;
902 Py_InteractiveFlag = 1;
903 Py_OptimizeFlag = 1;
904 Py_DebugFlag = 1;
905 Py_VerboseFlag = 1;
906 Py_QuietFlag = 1;
907 Py_FrozenFlag = 0;
908 Py_UnbufferedStdioFlag = 1;
909 Py_NoSiteFlag = 1;
910 Py_DontWriteBytecodeFlag = 1;
911 Py_NoUserSiteDirectory = 1;
912#ifdef MS_WINDOWS
913 Py_LegacyWindowsStdioFlag = 1;
914#endif
915}
916
917
Victor Stinner6d1c4672019-05-20 11:02:00 +0200918static int check_preinit_isolated_config(int preinit)
Victor Stinner56b29b62018-07-26 18:57:56 +0200919{
Victor Stinner331a6a52019-05-27 16:39:22 +0200920 PyStatus status;
921 PyPreConfig *rt_preconfig;
Victor Stinnercab5d072019-05-17 19:01:14 +0200922
Victor Stinnerbab0db62019-05-18 03:21:27 +0200923 /* environment variables must be ignored */
924 set_all_env_vars();
925
926 /* global configuration variables must be ignored */
927 set_all_global_config_variables();
928
Victor Stinner6d1c4672019-05-20 11:02:00 +0200929 if (preinit) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200930 PyPreConfig preconfig;
Victor Stinner3c30a762019-10-01 10:56:37 +0200931 PyPreConfig_InitIsolatedConfig(&preconfig);
Victor Stinnercab5d072019-05-17 19:01:14 +0200932
Victor Stinner331a6a52019-05-27 16:39:22 +0200933 status = Py_PreInitialize(&preconfig);
934 if (PyStatus_Exception(status)) {
935 Py_ExitStatusException(status);
Victor Stinner6d1c4672019-05-20 11:02:00 +0200936 }
937
938 rt_preconfig = &_PyRuntime.preconfig;
939 assert(rt_preconfig->isolated == 1);
940 assert(rt_preconfig->use_environment == 0);
Victor Stinnercab5d072019-05-17 19:01:14 +0200941 }
942
Victor Stinner331a6a52019-05-27 16:39:22 +0200943 PyConfig config;
Victor Stinner8462a492019-10-01 12:06:16 +0200944 PyConfig_InitIsolatedConfig(&config);
Victor Stinner441b10c2019-09-28 04:28:35 +0200945
Victor Stinner67310022019-07-01 19:52:45 +0200946 config_set_program_name(&config);
947 init_from_config_clear(&config);
Victor Stinner6d1c4672019-05-20 11:02:00 +0200948
949 rt_preconfig = &_PyRuntime.preconfig;
950 assert(rt_preconfig->isolated == 1);
951 assert(rt_preconfig->use_environment == 0);
952
Victor Stinnercab5d072019-05-17 19:01:14 +0200953 dump_config();
954 Py_Finalize();
955 return 0;
956}
957
958
Victor Stinner6d1c4672019-05-20 11:02:00 +0200959static int test_preinit_isolated_config(void)
960{
961 return check_preinit_isolated_config(1);
962}
963
964
965static int test_init_isolated_config(void)
966{
967 return check_preinit_isolated_config(0);
968}
969
970
971static int check_init_python_config(int preinit)
Victor Stinnercab5d072019-05-17 19:01:14 +0200972{
Victor Stinnerbab0db62019-05-18 03:21:27 +0200973 /* global configuration variables must be ignored */
974 set_all_global_config_variables();
975 Py_IsolatedFlag = 1;
976 Py_IgnoreEnvironmentFlag = 1;
977 Py_FrozenFlag = 1;
978 Py_UnbufferedStdioFlag = 1;
979 Py_NoSiteFlag = 1;
980 Py_DontWriteBytecodeFlag = 1;
981 Py_NoUserSiteDirectory = 1;
982#ifdef MS_WINDOWS
983 Py_LegacyWindowsStdioFlag = 1;
984#endif
985
Victor Stinner6d1c4672019-05-20 11:02:00 +0200986 if (preinit) {
Victor Stinner331a6a52019-05-27 16:39:22 +0200987 PyPreConfig preconfig;
Victor Stinner3c30a762019-10-01 10:56:37 +0200988 PyPreConfig_InitPythonConfig(&preconfig);
Victor Stinnercab5d072019-05-17 19:01:14 +0200989
Victor Stinner8462a492019-10-01 12:06:16 +0200990 PyStatus status = Py_PreInitialize(&preconfig);
Victor Stinner331a6a52019-05-27 16:39:22 +0200991 if (PyStatus_Exception(status)) {
992 Py_ExitStatusException(status);
Victor Stinner6d1c4672019-05-20 11:02:00 +0200993 }
Victor Stinnercab5d072019-05-17 19:01:14 +0200994 }
995
Victor Stinner331a6a52019-05-27 16:39:22 +0200996 PyConfig config;
Victor Stinner8462a492019-10-01 12:06:16 +0200997 PyConfig_InitPythonConfig(&config);
Victor Stinner441b10c2019-09-28 04:28:35 +0200998
Victor Stinner67310022019-07-01 19:52:45 +0200999 config_set_program_name(&config);
1000 init_from_config_clear(&config);
Victor Stinnercab5d072019-05-17 19:01:14 +02001001
Victor Stinnercab5d072019-05-17 19:01:14 +02001002 dump_config();
1003 Py_Finalize();
1004 return 0;
1005}
1006
1007
Victor Stinner6d1c4672019-05-20 11:02:00 +02001008static int test_preinit_python_config(void)
1009{
1010 return check_init_python_config(1);
1011}
1012
1013
1014static int test_init_python_config(void)
1015{
1016 return check_init_python_config(0);
1017}
1018
1019
Victor Stinnerbab0db62019-05-18 03:21:27 +02001020static int test_init_dont_configure_locale(void)
Victor Stinnerbcfbbd72019-05-17 22:44:16 +02001021{
Victor Stinner331a6a52019-05-27 16:39:22 +02001022 PyPreConfig preconfig;
Victor Stinner3c30a762019-10-01 10:56:37 +02001023 PyPreConfig_InitPythonConfig(&preconfig);
Victor Stinner441b10c2019-09-28 04:28:35 +02001024
Victor Stinnerbcfbbd72019-05-17 22:44:16 +02001025 preconfig.configure_locale = 0;
1026 preconfig.coerce_c_locale = 1;
1027 preconfig.coerce_c_locale_warn = 1;
1028
Victor Stinner3c30a762019-10-01 10:56:37 +02001029 PyStatus status = Py_PreInitialize(&preconfig);
Victor Stinner331a6a52019-05-27 16:39:22 +02001030 if (PyStatus_Exception(status)) {
1031 Py_ExitStatusException(status);
Victor Stinnerbcfbbd72019-05-17 22:44:16 +02001032 }
1033
Victor Stinner331a6a52019-05-27 16:39:22 +02001034 PyConfig config;
Victor Stinner8462a492019-10-01 12:06:16 +02001035 PyConfig_InitPythonConfig(&config);
Victor Stinner441b10c2019-09-28 04:28:35 +02001036
Victor Stinner67310022019-07-01 19:52:45 +02001037 config_set_program_name(&config);
1038 init_from_config_clear(&config);
Victor Stinnerbcfbbd72019-05-17 22:44:16 +02001039
1040 dump_config();
1041 Py_Finalize();
1042 return 0;
1043}
1044
1045
Victor Stinnerbab0db62019-05-18 03:21:27 +02001046static int test_init_dev_mode(void)
Victor Stinnercab5d072019-05-17 19:01:14 +02001047{
Victor Stinner331a6a52019-05-27 16:39:22 +02001048 PyConfig config;
Victor Stinner8462a492019-10-01 12:06:16 +02001049 PyConfig_InitPythonConfig(&config);
Victor Stinner441b10c2019-09-28 04:28:35 +02001050
Victor Stinner56b29b62018-07-26 18:57:56 +02001051 putenv("PYTHONFAULTHANDLER=");
1052 putenv("PYTHONMALLOC=");
Victor Stinner20004952019-03-26 02:31:11 +01001053 config.dev_mode = 1;
Victor Stinner67310022019-07-01 19:52:45 +02001054 config_set_program_name(&config);
1055 init_from_config_clear(&config);
1056
Victor Stinner56b29b62018-07-26 18:57:56 +02001057 dump_config();
1058 Py_Finalize();
1059 return 0;
1060}
1061
Steve Dowerb82e17e2019-05-23 08:45:22 -07001062static PyObject *_open_code_hook(PyObject *path, void *data)
1063{
1064 if (PyUnicode_CompareWithASCIIString(path, "$$test-filename") == 0) {
1065 return PyLong_FromVoidPtr(data);
1066 }
1067 PyObject *io = PyImport_ImportModule("_io");
1068 if (!io) {
1069 return NULL;
1070 }
1071 return PyObject_CallMethod(io, "open", "Os", path, "rb");
1072}
1073
1074static int test_open_code_hook(void)
1075{
1076 int result = 0;
1077
1078 /* Provide a hook */
1079 result = PyFile_SetOpenCodeHook(_open_code_hook, &result);
1080 if (result) {
1081 printf("Failed to set hook\n");
1082 return 1;
1083 }
1084 /* A second hook should fail */
1085 result = PyFile_SetOpenCodeHook(_open_code_hook, &result);
1086 if (!result) {
1087 printf("Should have failed to set second hook\n");
1088 return 2;
1089 }
1090
1091 Py_IgnoreEnvironmentFlag = 0;
1092 _testembed_Py_Initialize();
1093 result = 0;
1094
1095 PyObject *r = PyFile_OpenCode("$$test-filename");
1096 if (!r) {
1097 PyErr_Print();
1098 result = 3;
1099 } else {
1100 void *cmp = PyLong_AsVoidPtr(r);
1101 Py_DECREF(r);
1102 if (cmp != &result) {
1103 printf("Did not get expected result from hook\n");
1104 result = 4;
1105 }
1106 }
1107
1108 if (!result) {
1109 PyObject *io = PyImport_ImportModule("_io");
1110 PyObject *r = io
1111 ? PyObject_CallMethod(io, "open_code", "s", "$$test-filename")
1112 : NULL;
1113 if (!r) {
1114 PyErr_Print();
1115 result = 5;
1116 } else {
1117 void *cmp = PyLong_AsVoidPtr(r);
1118 Py_DECREF(r);
1119 if (cmp != &result) {
1120 printf("Did not get expected result from hook\n");
1121 result = 6;
1122 }
1123 }
1124 Py_XDECREF(io);
1125 }
1126
1127 Py_Finalize();
1128 return result;
1129}
1130
Kongedaa0fe02020-07-04 05:06:46 +08001131static int _audit_hook_clear_count = 0;
1132
Steve Dowerb82e17e2019-05-23 08:45:22 -07001133static int _audit_hook(const char *event, PyObject *args, void *userdata)
1134{
Kongedaa0fe02020-07-04 05:06:46 +08001135 assert(args && PyTuple_CheckExact(args));
Steve Dowerb82e17e2019-05-23 08:45:22 -07001136 if (strcmp(event, "_testembed.raise") == 0) {
1137 PyErr_SetString(PyExc_RuntimeError, "Intentional error");
1138 return -1;
1139 } else if (strcmp(event, "_testembed.set") == 0) {
1140 if (!PyArg_ParseTuple(args, "n", userdata)) {
1141 return -1;
1142 }
1143 return 0;
Kongedaa0fe02020-07-04 05:06:46 +08001144 } else if (strcmp(event, "cpython._PySys_ClearAuditHooks") == 0) {
1145 _audit_hook_clear_count += 1;
Steve Dowerb82e17e2019-05-23 08:45:22 -07001146 }
1147 return 0;
1148}
1149
1150static int _test_audit(Py_ssize_t setValue)
1151{
1152 Py_ssize_t sawSet = 0;
1153
1154 Py_IgnoreEnvironmentFlag = 0;
1155 PySys_AddAuditHook(_audit_hook, &sawSet);
1156 _testembed_Py_Initialize();
1157
1158 if (PySys_Audit("_testembed.raise", NULL) == 0) {
1159 printf("No error raised");
1160 return 1;
1161 }
1162 if (PySys_Audit("_testembed.nop", NULL) != 0) {
1163 printf("Nop event failed");
1164 /* Exception from above may still remain */
1165 PyErr_Clear();
1166 return 2;
1167 }
1168 if (!PyErr_Occurred()) {
1169 printf("Exception not preserved");
1170 return 3;
1171 }
1172 PyErr_Clear();
1173
1174 if (PySys_Audit("_testembed.set", "n", setValue) != 0) {
1175 PyErr_Print();
1176 printf("Set event failed");
1177 return 4;
1178 }
1179
1180 if (sawSet != 42) {
1181 printf("Failed to see *userData change\n");
1182 return 5;
1183 }
1184 return 0;
1185}
1186
1187static int test_audit(void)
1188{
1189 int result = _test_audit(42);
1190 Py_Finalize();
Kongedaa0fe02020-07-04 05:06:46 +08001191 if (_audit_hook_clear_count != 1) {
1192 return 0x1000 | _audit_hook_clear_count;
1193 }
Steve Dowerb82e17e2019-05-23 08:45:22 -07001194 return result;
1195}
1196
1197static volatile int _audit_subinterpreter_interpreter_count = 0;
1198
1199static int _audit_subinterpreter_hook(const char *event, PyObject *args, void *userdata)
1200{
1201 printf("%s\n", event);
1202 if (strcmp(event, "cpython.PyInterpreterState_New") == 0) {
1203 _audit_subinterpreter_interpreter_count += 1;
1204 }
1205 return 0;
1206}
1207
1208static int test_audit_subinterpreter(void)
1209{
Steve Dowerb82e17e2019-05-23 08:45:22 -07001210 Py_IgnoreEnvironmentFlag = 0;
1211 PySys_AddAuditHook(_audit_subinterpreter_hook, NULL);
1212 _testembed_Py_Initialize();
1213
Pablo Galindocccc11b2019-05-24 00:53:21 +01001214 Py_NewInterpreter();
1215 Py_NewInterpreter();
1216 Py_NewInterpreter();
Steve Dowerb82e17e2019-05-23 08:45:22 -07001217
1218 Py_Finalize();
1219
1220 switch (_audit_subinterpreter_interpreter_count) {
1221 case 3: return 0;
1222 case 0: return -1;
1223 default: return _audit_subinterpreter_interpreter_count;
1224 }
1225}
Victor Stinner56b29b62018-07-26 18:57:56 +02001226
Steve Dowere226e832019-07-01 16:03:53 -07001227typedef struct {
1228 const char* expected;
1229 int exit;
1230} AuditRunCommandTest;
1231
1232static int _audit_hook_run(const char *eventName, PyObject *args, void *userData)
1233{
1234 AuditRunCommandTest *test = (AuditRunCommandTest*)userData;
1235 if (strcmp(eventName, test->expected)) {
1236 return 0;
1237 }
1238
1239 if (test->exit) {
1240 PyObject *msg = PyUnicode_FromFormat("detected %s(%R)", eventName, args);
1241 if (msg) {
1242 printf("%s\n", PyUnicode_AsUTF8(msg));
1243 Py_DECREF(msg);
1244 }
1245 exit(test->exit);
1246 }
1247
1248 PyErr_Format(PyExc_RuntimeError, "detected %s(%R)", eventName, args);
1249 return -1;
1250}
1251
1252static int test_audit_run_command(void)
1253{
1254 AuditRunCommandTest test = {"cpython.run_command"};
Victor Stinnerbb6bf7d2019-09-24 18:21:02 +02001255 wchar_t *argv[] = {PROGRAM_NAME, L"-c", L"pass"};
Steve Dowere226e832019-07-01 16:03:53 -07001256
1257 Py_IgnoreEnvironmentFlag = 0;
1258 PySys_AddAuditHook(_audit_hook_run, (void*)&test);
1259
1260 return Py_Main(Py_ARRAY_LENGTH(argv), argv);
1261}
1262
1263static int test_audit_run_file(void)
1264{
1265 AuditRunCommandTest test = {"cpython.run_file"};
Victor Stinnerbb6bf7d2019-09-24 18:21:02 +02001266 wchar_t *argv[] = {PROGRAM_NAME, L"filename.py"};
Steve Dowere226e832019-07-01 16:03:53 -07001267
1268 Py_IgnoreEnvironmentFlag = 0;
1269 PySys_AddAuditHook(_audit_hook_run, (void*)&test);
1270
1271 return Py_Main(Py_ARRAY_LENGTH(argv), argv);
1272}
1273
1274static int run_audit_run_test(int argc, wchar_t **argv, void *test)
1275{
Steve Dowere226e832019-07-01 16:03:53 -07001276 PyConfig config;
Victor Stinner8462a492019-10-01 12:06:16 +02001277 PyConfig_InitPythonConfig(&config);
Victor Stinner441b10c2019-09-28 04:28:35 +02001278
Steve Dowere226e832019-07-01 16:03:53 -07001279 config.argv.length = argc;
1280 config.argv.items = argv;
1281 config.parse_argv = 1;
1282 config.program_name = argv[0];
1283 config.interactive = 1;
1284 config.isolated = 0;
1285 config.use_environment = 1;
1286 config.quiet = 1;
1287
1288 PySys_AddAuditHook(_audit_hook_run, test);
1289
Victor Stinner8462a492019-10-01 12:06:16 +02001290 PyStatus status = Py_InitializeFromConfig(&config);
Steve Dowere226e832019-07-01 16:03:53 -07001291 if (PyStatus_Exception(status)) {
1292 Py_ExitStatusException(status);
1293 }
1294
1295 return Py_RunMain();
1296}
1297
1298static int test_audit_run_interactivehook(void)
1299{
1300 AuditRunCommandTest test = {"cpython.run_interactivehook", 10};
Victor Stinnerbb6bf7d2019-09-24 18:21:02 +02001301 wchar_t *argv[] = {PROGRAM_NAME};
Steve Dowere226e832019-07-01 16:03:53 -07001302 return run_audit_run_test(Py_ARRAY_LENGTH(argv), argv, &test);
1303}
1304
1305static int test_audit_run_startup(void)
1306{
1307 AuditRunCommandTest test = {"cpython.run_startup", 10};
Victor Stinnerbb6bf7d2019-09-24 18:21:02 +02001308 wchar_t *argv[] = {PROGRAM_NAME};
Steve Dowere226e832019-07-01 16:03:53 -07001309 return run_audit_run_test(Py_ARRAY_LENGTH(argv), argv, &test);
1310}
1311
1312static int test_audit_run_stdin(void)
1313{
1314 AuditRunCommandTest test = {"cpython.run_stdin"};
Victor Stinnerbb6bf7d2019-09-24 18:21:02 +02001315 wchar_t *argv[] = {PROGRAM_NAME};
Steve Dowere226e832019-07-01 16:03:53 -07001316 return run_audit_run_test(Py_ARRAY_LENGTH(argv), argv, &test);
1317}
1318
Victor Stinner91c99872019-05-14 22:01:51 +02001319static int test_init_read_set(void)
1320{
Victor Stinner331a6a52019-05-27 16:39:22 +02001321 PyStatus status;
1322 PyConfig config;
Victor Stinner8462a492019-10-01 12:06:16 +02001323 PyConfig_InitPythonConfig(&config);
Victor Stinner91c99872019-05-14 22:01:51 +02001324
Victor Stinner331a6a52019-05-27 16:39:22 +02001325 status = PyConfig_SetBytesString(&config, &config.program_name,
Victor Stinner6d1c4672019-05-20 11:02:00 +02001326 "./init_read_set");
Victor Stinner331a6a52019-05-27 16:39:22 +02001327 if (PyStatus_Exception(status)) {
Victor Stinner91c99872019-05-14 22:01:51 +02001328 goto fail;
1329 }
1330
Victor Stinner331a6a52019-05-27 16:39:22 +02001331 status = PyConfig_Read(&config);
1332 if (PyStatus_Exception(status)) {
Victor Stinner91c99872019-05-14 22:01:51 +02001333 goto fail;
1334 }
1335
Victor Stinner3842f292019-08-23 16:57:54 +01001336 status = PyWideStringList_Insert(&config.module_search_paths,
1337 1, L"test_path_insert1");
1338 if (PyStatus_Exception(status)) {
1339 goto fail;
1340 }
1341
Victor Stinner331a6a52019-05-27 16:39:22 +02001342 status = PyWideStringList_Append(&config.module_search_paths,
Victor Stinner3842f292019-08-23 16:57:54 +01001343 L"test_path_append");
Victor Stinner331a6a52019-05-27 16:39:22 +02001344 if (PyStatus_Exception(status)) {
Victor Stinner91c99872019-05-14 22:01:51 +02001345 goto fail;
1346 }
1347
Victor Stinner331a6a52019-05-27 16:39:22 +02001348 /* override executable computed by PyConfig_Read() */
Victor Stinner67310022019-07-01 19:52:45 +02001349 config_set_string(&config, &config.executable, L"my_executable");
1350 init_from_config_clear(&config);
Victor Stinner91c99872019-05-14 22:01:51 +02001351
Victor Stinner91c99872019-05-14 22:01:51 +02001352 dump_config();
1353 Py_Finalize();
1354 return 0;
1355
1356fail:
Victor Stinnere81f6e62020-06-08 18:12:59 +02001357 PyConfig_Clear(&config);
Victor Stinner331a6a52019-05-27 16:39:22 +02001358 Py_ExitStatusException(status);
Victor Stinner91c99872019-05-14 22:01:51 +02001359}
1360
1361
Victor Stinner120b7072019-08-23 18:03:08 +01001362static int test_init_sys_add(void)
1363{
1364 PySys_AddXOption(L"sysadd_xoption");
1365 PySys_AddXOption(L"faulthandler");
1366 PySys_AddWarnOption(L"ignore:::sysadd_warnoption");
1367
1368 PyConfig config;
Victor Stinner8462a492019-10-01 12:06:16 +02001369 PyConfig_InitPythonConfig(&config);
Victor Stinner120b7072019-08-23 18:03:08 +01001370
1371 wchar_t* argv[] = {
1372 L"python3",
1373 L"-W",
1374 L"ignore:::cmdline_warnoption",
1375 L"-X",
1376 L"cmdline_xoption",
1377 };
1378 config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
1379 config.parse_argv = 1;
1380
Victor Stinner8462a492019-10-01 12:06:16 +02001381 PyStatus status;
Victor Stinner120b7072019-08-23 18:03:08 +01001382 status = PyWideStringList_Append(&config.xoptions,
1383 L"config_xoption");
1384 if (PyStatus_Exception(status)) {
1385 goto fail;
1386 }
1387
1388 status = PyWideStringList_Append(&config.warnoptions,
1389 L"ignore:::config_warnoption");
1390 if (PyStatus_Exception(status)) {
1391 goto fail;
1392 }
1393
1394 config_set_program_name(&config);
1395 init_from_config_clear(&config);
1396
1397 dump_config();
1398 Py_Finalize();
1399 return 0;
1400
1401fail:
1402 PyConfig_Clear(&config);
1403 Py_ExitStatusException(status);
1404}
1405
1406
Victor Stinnerbb6bf7d2019-09-24 18:21:02 +02001407static int test_init_setpath(void)
1408{
Victor Stinnerbb6bf7d2019-09-24 18:21:02 +02001409 char *env = getenv("TESTPATH");
1410 if (!env) {
1411 fprintf(stderr, "missing TESTPATH env var\n");
1412 return 1;
1413 }
1414 wchar_t *path = Py_DecodeLocale(env, NULL);
1415 if (path == NULL) {
1416 fprintf(stderr, "failed to decode TESTPATH\n");
1417 return 1;
1418 }
1419 Py_SetPath(path);
1420 PyMem_RawFree(path);
1421 putenv("TESTPATH=");
1422
1423 Py_Initialize();
1424 dump_config();
1425 Py_Finalize();
1426 return 0;
1427}
1428
1429
Victor Stinner8bf39b62019-09-26 02:22:35 +02001430static int test_init_setpath_config(void)
Victor Stinnerbb6bf7d2019-09-24 18:21:02 +02001431{
Victor Stinner49d99f02019-09-26 04:01:49 +02001432 PyPreConfig preconfig;
Victor Stinner3c30a762019-10-01 10:56:37 +02001433 PyPreConfig_InitPythonConfig(&preconfig);
Victor Stinner49d99f02019-09-26 04:01:49 +02001434
1435 /* Explicitly preinitializes with Python preconfiguration to avoid
1436 Py_SetPath() implicit preinitialization with compat preconfiguration. */
Victor Stinner3c30a762019-10-01 10:56:37 +02001437 PyStatus status = Py_PreInitialize(&preconfig);
Victor Stinner49d99f02019-09-26 04:01:49 +02001438 if (PyStatus_Exception(status)) {
1439 Py_ExitStatusException(status);
1440 }
1441
Victor Stinner8bf39b62019-09-26 02:22:35 +02001442 char *env = getenv("TESTPATH");
1443 if (!env) {
1444 fprintf(stderr, "missing TESTPATH env var\n");
1445 return 1;
Victor Stinnerbb6bf7d2019-09-24 18:21:02 +02001446 }
Victor Stinner8bf39b62019-09-26 02:22:35 +02001447 wchar_t *path = Py_DecodeLocale(env, NULL);
1448 if (path == NULL) {
1449 fprintf(stderr, "failed to decode TESTPATH\n");
1450 return 1;
1451 }
1452 Py_SetPath(path);
1453 PyMem_RawFree(path);
1454 putenv("TESTPATH=");
Victor Stinnerbb6bf7d2019-09-24 18:21:02 +02001455
Victor Stinner8bf39b62019-09-26 02:22:35 +02001456 PyConfig config;
Victor Stinner8462a492019-10-01 12:06:16 +02001457 PyConfig_InitPythonConfig(&config);
Victor Stinnerbb6bf7d2019-09-24 18:21:02 +02001458
Victor Stinner8bf39b62019-09-26 02:22:35 +02001459 config_set_string(&config, &config.program_name, L"conf_program_name");
1460 config_set_string(&config, &config.executable, L"conf_executable");
1461 init_from_config_clear(&config);
Victor Stinnerbb6bf7d2019-09-24 18:21:02 +02001462
Victor Stinner8bf39b62019-09-26 02:22:35 +02001463 dump_config();
1464 Py_Finalize();
Victor Stinnerbb6bf7d2019-09-24 18:21:02 +02001465 return 0;
1466}
1467
1468
1469static int test_init_setpythonhome(void)
1470{
1471 char *env = getenv("TESTHOME");
1472 if (!env) {
1473 fprintf(stderr, "missing TESTHOME env var\n");
1474 return 1;
1475 }
1476 wchar_t *home = Py_DecodeLocale(env, NULL);
1477 if (home == NULL) {
1478 fprintf(stderr, "failed to decode TESTHOME\n");
1479 return 1;
1480 }
1481 Py_SetPythonHome(home);
1482 PyMem_RawFree(home);
1483 putenv("TESTHOME=");
1484
Victor Stinnerbb6bf7d2019-09-24 18:21:02 +02001485 Py_Initialize();
1486 dump_config();
1487 Py_Finalize();
1488 return 0;
1489}
1490
1491
Victor Stinnerfb4ae152019-09-30 01:40:17 +02001492static int test_init_warnoptions(void)
1493{
Victor Stinnerfb4ae152019-09-30 01:40:17 +02001494 putenv("PYTHONWARNINGS=ignore:::env1,ignore:::env2");
1495
1496 PySys_AddWarnOption(L"ignore:::PySys_AddWarnOption1");
1497 PySys_AddWarnOption(L"ignore:::PySys_AddWarnOption2");
1498
1499 PyConfig config;
Victor Stinner8462a492019-10-01 12:06:16 +02001500 PyConfig_InitPythonConfig(&config);
Victor Stinnerfb4ae152019-09-30 01:40:17 +02001501
1502 config.dev_mode = 1;
1503 config.bytes_warning = 1;
1504
1505 config_set_program_name(&config);
1506
Victor Stinner8462a492019-10-01 12:06:16 +02001507 PyStatus status;
Victor Stinnerfb4ae152019-09-30 01:40:17 +02001508 status = PyWideStringList_Append(&config.warnoptions,
1509 L"ignore:::PyConfig_BeforeRead");
1510 if (PyStatus_Exception(status)) {
1511 Py_ExitStatusException(status);
1512 }
1513
1514 wchar_t* argv[] = {
1515 L"python3",
1516 L"-Wignore:::cmdline1",
1517 L"-Wignore:::cmdline2"};
1518 config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
1519 config.parse_argv = 1;
1520
1521 status = PyConfig_Read(&config);
1522 if (PyStatus_Exception(status)) {
1523 Py_ExitStatusException(status);
1524 }
1525
1526 status = PyWideStringList_Append(&config.warnoptions,
1527 L"ignore:::PyConfig_AfterRead");
1528 if (PyStatus_Exception(status)) {
1529 Py_ExitStatusException(status);
1530 }
1531
1532 status = PyWideStringList_Insert(&config.warnoptions,
1533 0, L"ignore:::PyConfig_Insert0");
1534 if (PyStatus_Exception(status)) {
1535 Py_ExitStatusException(status);
1536 }
1537
1538 init_from_config_clear(&config);
1539 dump_config();
1540 Py_Finalize();
1541 return 0;
1542}
1543
1544
Victor Stinner048a3562020-11-05 00:45:56 +01001545static int tune_config(void)
1546{
1547 PyConfig config;
1548 PyConfig_InitPythonConfig(&config);
1549 if (_PyInterpreterState_GetConfigCopy(&config) < 0) {
1550 PyConfig_Clear(&config);
1551 PyErr_Print();
1552 return -1;
1553 }
1554
1555 config.bytes_warning = 2;
1556
1557 if (_PyInterpreterState_SetConfig(&config) < 0) {
1558 PyConfig_Clear(&config);
1559 return -1;
1560 }
1561 PyConfig_Clear(&config);
1562 return 0;
1563}
1564
1565
Victor Stinner9e1b8282020-11-10 13:21:52 +01001566static int test_init_set_config(void)
Victor Stinner048a3562020-11-05 00:45:56 +01001567{
1568 // Initialize core
1569 PyConfig config;
1570 PyConfig_InitIsolatedConfig(&config);
1571 config_set_string(&config, &config.program_name, PROGRAM_NAME);
1572 config._init_main = 0;
1573 config.bytes_warning = 0;
1574 init_from_config_clear(&config);
1575
1576 // Tune the configuration using _PyInterpreterState_SetConfig()
1577 if (tune_config() < 0) {
1578 PyErr_Print();
1579 return 1;
1580 }
1581
1582 // Finish initialization: main part
1583 PyStatus status = _Py_InitializeMain();
1584 if (PyStatus_Exception(status)) {
1585 Py_ExitStatusException(status);
1586 }
1587
1588 dump_config();
1589 Py_Finalize();
1590 return 0;
1591}
1592
1593
Victor Stinner331a6a52019-05-27 16:39:22 +02001594static void configure_init_main(PyConfig *config)
Victor Stinner9ef5dca2019-05-16 17:38:16 +02001595{
Victor Stinner67310022019-07-01 19:52:45 +02001596 wchar_t* argv[] = {
1597 L"python3", L"-c",
1598 (L"import _testinternalcapi, json; "
1599 L"print(json.dumps(_testinternalcapi.get_configs()))"),
1600 L"arg2"};
1601
Victor Stinnercab5d072019-05-17 19:01:14 +02001602 config->parse_argv = 1;
Victor Stinner67310022019-07-01 19:52:45 +02001603
1604 config_set_argv(config, Py_ARRAY_LENGTH(argv), argv);
1605 config_set_string(config, &config->program_name, L"./python3");
Victor Stinner9ef5dca2019-05-16 17:38:16 +02001606}
1607
1608
1609static int test_init_run_main(void)
Victor Stinner2f549082019-03-29 15:13:46 +01001610{
Victor Stinner331a6a52019-05-27 16:39:22 +02001611 PyConfig config;
Victor Stinner8462a492019-10-01 12:06:16 +02001612 PyConfig_InitPythonConfig(&config);
Victor Stinner441b10c2019-09-28 04:28:35 +02001613
Victor Stinner9ef5dca2019-05-16 17:38:16 +02001614 configure_init_main(&config);
Victor Stinner67310022019-07-01 19:52:45 +02001615 init_from_config_clear(&config);
Victor Stinner2f549082019-03-29 15:13:46 +01001616
Victor Stinner331a6a52019-05-27 16:39:22 +02001617 return Py_RunMain();
Victor Stinner2f549082019-03-29 15:13:46 +01001618}
1619
1620
Victor Stinner9ef5dca2019-05-16 17:38:16 +02001621static int test_init_main(void)
1622{
Victor Stinner331a6a52019-05-27 16:39:22 +02001623 PyConfig config;
Victor Stinner8462a492019-10-01 12:06:16 +02001624 PyConfig_InitPythonConfig(&config);
Victor Stinner6d1c4672019-05-20 11:02:00 +02001625
Victor Stinner9ef5dca2019-05-16 17:38:16 +02001626 configure_init_main(&config);
1627 config._init_main = 0;
Victor Stinner67310022019-07-01 19:52:45 +02001628 init_from_config_clear(&config);
Victor Stinner9ef5dca2019-05-16 17:38:16 +02001629
1630 /* sys.stdout don't exist yet: it is created by _Py_InitializeMain() */
1631 int res = PyRun_SimpleString(
1632 "import sys; "
1633 "print('Run Python code before _Py_InitializeMain', "
1634 "file=sys.stderr)");
1635 if (res < 0) {
1636 exit(1);
1637 }
1638
Victor Stinner8462a492019-10-01 12:06:16 +02001639 PyStatus status = _Py_InitializeMain();
Victor Stinner331a6a52019-05-27 16:39:22 +02001640 if (PyStatus_Exception(status)) {
1641 Py_ExitStatusException(status);
Victor Stinner9ef5dca2019-05-16 17:38:16 +02001642 }
1643
Victor Stinner331a6a52019-05-27 16:39:22 +02001644 return Py_RunMain();
Victor Stinner9ef5dca2019-05-16 17:38:16 +02001645}
1646
1647
1648static int test_run_main(void)
Victor Stinner5eb8b072019-05-15 02:12:48 +02001649{
Victor Stinner331a6a52019-05-27 16:39:22 +02001650 PyConfig config;
Victor Stinner8462a492019-10-01 12:06:16 +02001651 PyConfig_InitPythonConfig(&config);
Victor Stinner5eb8b072019-05-15 02:12:48 +02001652
1653 wchar_t *argv[] = {L"python3", L"-c",
Victor Stinner9ef5dca2019-05-16 17:38:16 +02001654 (L"import sys; "
Victor Stinner331a6a52019-05-27 16:39:22 +02001655 L"print(f'Py_RunMain(): sys.argv={sys.argv}')"),
Victor Stinner5eb8b072019-05-15 02:12:48 +02001656 L"arg2"};
Victor Stinner67310022019-07-01 19:52:45 +02001657 config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
1658 config_set_string(&config, &config.program_name, L"./python3");
1659 init_from_config_clear(&config);
Victor Stinner6d1c4672019-05-20 11:02:00 +02001660
Victor Stinner331a6a52019-05-27 16:39:22 +02001661 return Py_RunMain();
Victor Stinner5eb8b072019-05-15 02:12:48 +02001662}
1663
1664
Victor Stinnere81f6e62020-06-08 18:12:59 +02001665static int test_get_argc_argv(void)
1666{
1667 PyConfig config;
1668 PyConfig_InitPythonConfig(&config);
1669
1670 wchar_t *argv[] = {L"python3", L"-c",
1671 (L"import sys; "
1672 L"print(f'Py_RunMain(): sys.argv={sys.argv}')"),
1673 L"arg2"};
1674 config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
1675 config_set_string(&config, &config.program_name, L"./python3");
1676
1677 // Calling PyConfig_Read() twice must not change Py_GetArgcArgv() result.
1678 // The second call is done by Py_InitializeFromConfig().
1679 PyStatus status = PyConfig_Read(&config);
1680 if (PyStatus_Exception(status)) {
1681 PyConfig_Clear(&config);
1682 Py_ExitStatusException(status);
1683 }
1684
1685 init_from_config_clear(&config);
1686
1687 int get_argc;
1688 wchar_t **get_argv;
1689 Py_GetArgcArgv(&get_argc, &get_argv);
1690 printf("argc: %i\n", get_argc);
1691 assert(get_argc == Py_ARRAY_LENGTH(argv));
1692 for (int i=0; i < get_argc; i++) {
1693 printf("argv[%i]: %ls\n", i, get_argv[i]);
1694 assert(wcscmp(get_argv[i], argv[i]) == 0);
1695 }
1696
1697 Py_Finalize();
1698
1699 printf("\n");
1700 printf("test ok\n");
1701 return 0;
1702}
1703
1704
Victor Stinner11d13e82021-01-12 11:26:26 +01001705static int test_unicode_id_init(void)
1706{
1707 // bpo-42882: Test that _PyUnicode_FromId() works
1708 // when Python is initialized multiples times.
1709 _Py_IDENTIFIER(test_unicode_id_init);
1710
1711 // Initialize Python once without using the identifier
1712 _testembed_Py_Initialize();
1713 Py_Finalize();
1714
1715 // Now initialize Python multiple times and use the identifier.
1716 // The first _PyUnicode_FromId() call initializes the identifier index.
1717 for (int i=0; i<3; i++) {
1718 _testembed_Py_Initialize();
1719
1720 PyObject *str1, *str2;
1721
1722 str1 = _PyUnicode_FromId(&PyId_test_unicode_id_init);
1723 assert(str1 != NULL);
1724 assert(Py_REFCNT(str1) == 1);
1725
1726 str2 = PyUnicode_FromString("test_unicode_id_init");
1727 assert(str2 != NULL);
1728
1729 assert(PyUnicode_Compare(str1, str2) == 0);
1730
1731 // str1 is a borrowed reference
1732 Py_DECREF(str2);
1733
1734 Py_Finalize();
1735 }
1736 return 0;
1737}
1738
1739
Victor Stinner307745a2021-03-10 11:14:07 +01001740// List frozen modules.
1741// Command used by Tools/scripts/generate_stdlib_module_names.py script.
1742static int list_frozen(void)
1743{
1744 const struct _frozen *p;
1745 for (p = PyImport_FrozenModules; ; p++) {
1746 if (p->name == NULL)
1747 break;
1748 printf("%s\n", p->name);
1749 }
1750 return 0;
1751}
1752
1753
Victor Stinnerece38412021-06-23 17:47:38 +02001754static int test_repeated_init_and_inittab(void)
1755{
1756 // bpo-44441: Py_RunMain() must reset PyImport_Inittab at exit.
1757 // It must be possible to call PyImport_AppendInittab() or
1758 // PyImport_ExtendInittab() before each Python initialization.
1759 for (int i=1; i <= INIT_LOOPS; i++) {
1760 printf("--- Pass %d ---\n", i);
1761
1762 // Call PyImport_AppendInittab() at each iteration
1763 if (PyImport_AppendInittab(EMBEDDED_EXT_NAME,
1764 &PyInit_embedded_ext) != 0) {
1765 fprintf(stderr, "PyImport_AppendInittab() failed\n");
1766 return 1;
1767 }
1768
1769 // Initialize Python
1770 wchar_t* argv[] = {PROGRAM_NAME, L"-c", L"pass"};
1771 PyConfig config;
1772 PyConfig_InitPythonConfig(&config);
1773 config.isolated = 1;
1774 config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
1775 init_from_config_clear(&config);
1776
1777 // Py_RunMain() calls _PyImport_Fini2() which resets PyImport_Inittab
1778 int exitcode = Py_RunMain();
1779 if (exitcode != 0) {
1780 return exitcode;
1781 }
1782 }
1783 return 0;
1784}
1785
Victor Stinner11d13e82021-01-12 11:26:26 +01001786
Steve Dowerea74f0c2017-01-01 20:25:03 -08001787/* *********************************************************
1788 * List of test cases and the function that implements it.
Serhiy Storchaka13ad3b72017-09-14 09:38:36 +03001789 *
Steve Dowerea74f0c2017-01-01 20:25:03 -08001790 * Names are compared case-sensitively with the first
1791 * argument. If no match is found, or no first argument was
1792 * provided, the names of all test cases are printed and
1793 * the exit code will be -1.
1794 *
1795 * The int returned from test functions is used as the exit
1796 * code, and test_capi treats all non-zero exit codes as a
Serhiy Storchaka13ad3b72017-09-14 09:38:36 +03001797 * failed test.
Steve Dowerea74f0c2017-01-01 20:25:03 -08001798 *********************************************************/
1799struct TestCase
1800{
1801 const char *name;
1802 int (*func)(void);
1803};
1804
1805static struct TestCase TestCases[] = {
Victor Stinnerece38412021-06-23 17:47:38 +02001806 // Python initialization
Victor Stinner5edcf262019-05-23 00:57:57 +02001807 {"test_forced_io_encoding", test_forced_io_encoding},
1808 {"test_repeated_init_and_subinterpreters", test_repeated_init_and_subinterpreters},
Victor Stinnerece38412021-06-23 17:47:38 +02001809 {"test_repeated_init_and_inittab", test_repeated_init_and_inittab},
Victor Stinner5edcf262019-05-23 00:57:57 +02001810 {"test_pre_initialization_api", test_pre_initialization_api},
1811 {"test_pre_initialization_sys_options", test_pre_initialization_sys_options},
1812 {"test_bpo20891", test_bpo20891},
1813 {"test_initialize_twice", test_initialize_twice},
1814 {"test_initialize_pymain", test_initialize_pymain},
1815 {"test_init_initialize_config", test_init_initialize_config},
1816 {"test_preinit_compat_config", test_preinit_compat_config},
1817 {"test_init_compat_config", test_init_compat_config},
1818 {"test_init_global_config", test_init_global_config},
1819 {"test_init_from_config", test_init_from_config},
1820 {"test_init_parse_argv", test_init_parse_argv},
1821 {"test_init_dont_parse_argv", test_init_dont_parse_argv},
Victor Stinner20e1e252019-05-23 04:12:27 +02001822 {"test_init_compat_env", test_init_compat_env},
1823 {"test_init_python_env", test_init_python_env},
Victor Stinner5edcf262019-05-23 00:57:57 +02001824 {"test_init_env_dev_mode", test_init_env_dev_mode},
1825 {"test_init_env_dev_mode_alloc", test_init_env_dev_mode_alloc},
1826 {"test_init_dont_configure_locale", test_init_dont_configure_locale},
1827 {"test_init_dev_mode", test_init_dev_mode},
1828 {"test_init_isolated_flag", test_init_isolated_flag},
1829 {"test_preinit_isolated_config", test_preinit_isolated_config},
1830 {"test_init_isolated_config", test_init_isolated_config},
1831 {"test_preinit_python_config", test_preinit_python_config},
1832 {"test_init_python_config", test_init_python_config},
1833 {"test_preinit_isolated1", test_preinit_isolated1},
1834 {"test_preinit_isolated2", test_preinit_isolated2},
1835 {"test_preinit_parse_argv", test_preinit_parse_argv},
1836 {"test_preinit_dont_parse_argv", test_preinit_dont_parse_argv},
1837 {"test_init_read_set", test_init_read_set},
1838 {"test_init_run_main", test_init_run_main},
1839 {"test_init_main", test_init_main},
Victor Stinner120b7072019-08-23 18:03:08 +01001840 {"test_init_sys_add", test_init_sys_add},
Victor Stinnerbb6bf7d2019-09-24 18:21:02 +02001841 {"test_init_setpath", test_init_setpath},
Victor Stinner8bf39b62019-09-26 02:22:35 +02001842 {"test_init_setpath_config", test_init_setpath_config},
Victor Stinnerbb6bf7d2019-09-24 18:21:02 +02001843 {"test_init_setpythonhome", test_init_setpythonhome},
Victor Stinnerfb4ae152019-09-30 01:40:17 +02001844 {"test_init_warnoptions", test_init_warnoptions},
Victor Stinner9e1b8282020-11-10 13:21:52 +01001845 {"test_init_set_config", test_init_set_config},
Victor Stinner5edcf262019-05-23 00:57:57 +02001846 {"test_run_main", test_run_main},
Victor Stinnere81f6e62020-06-08 18:12:59 +02001847 {"test_get_argc_argv", test_get_argc_argv},
Victor Stinnerbb6bf7d2019-09-24 18:21:02 +02001848
Victor Stinnerece38412021-06-23 17:47:38 +02001849 // Audit
Steve Dowerb82e17e2019-05-23 08:45:22 -07001850 {"test_open_code_hook", test_open_code_hook},
1851 {"test_audit", test_audit},
1852 {"test_audit_subinterpreter", test_audit_subinterpreter},
Steve Dowere226e832019-07-01 16:03:53 -07001853 {"test_audit_run_command", test_audit_run_command},
1854 {"test_audit_run_file", test_audit_run_file},
1855 {"test_audit_run_interactivehook", test_audit_run_interactivehook},
1856 {"test_audit_run_startup", test_audit_run_startup},
1857 {"test_audit_run_stdin", test_audit_run_stdin},
Victor Stinner11d13e82021-01-12 11:26:26 +01001858
Victor Stinnerece38412021-06-23 17:47:38 +02001859 // Specific C API
Victor Stinner11d13e82021-01-12 11:26:26 +01001860 {"test_unicode_id_init", test_unicode_id_init},
Victor Stinner307745a2021-03-10 11:14:07 +01001861
Victor Stinnerece38412021-06-23 17:47:38 +02001862 // Command
Victor Stinner307745a2021-03-10 11:14:07 +01001863 {"list_frozen", list_frozen},
Victor Stinner5edcf262019-05-23 00:57:57 +02001864 {NULL, NULL}
Steve Dowerea74f0c2017-01-01 20:25:03 -08001865};
1866
Nick Coghlan7d270ee2013-10-17 22:35:35 +10001867int main(int argc, char *argv[])
1868{
Nick Coghlan7d270ee2013-10-17 22:35:35 +10001869 if (argc > 1) {
Steve Dowerea74f0c2017-01-01 20:25:03 -08001870 for (struct TestCase *tc = TestCases; tc && tc->name; tc++) {
1871 if (strcmp(argv[1], tc->name) == 0)
1872 return (*tc->func)();
1873 }
Nick Coghlan7d270ee2013-10-17 22:35:35 +10001874 }
Steve Dowerea74f0c2017-01-01 20:25:03 -08001875
1876 /* No match found, or no test name provided, so display usage */
1877 printf("Python " PY_VERSION " _testembed executable for embedded interpreter tests\n"
Nick Coghlanbc77eff2018-03-25 20:44:30 +10001878 "Normally executed via 'EmbeddingTests' in Lib/test/test_embed.py\n\n"
Steve Dowerea74f0c2017-01-01 20:25:03 -08001879 "Usage: %s TESTNAME\n\nAll available tests:\n", argv[0]);
1880 for (struct TestCase *tc = TestCases; tc && tc->name; tc++) {
1881 printf(" %s\n", tc->name);
1882 }
1883
Nick Coghlanbc77eff2018-03-25 20:44:30 +10001884 /* Non-zero exit code will cause test_embed.py tests to fail.
Steve Dowerea74f0c2017-01-01 20:25:03 -08001885 This is intentional. */
1886 return -1;
Antoine Pitrou8e605772011-04-25 21:21:07 +02001887}