blob: 7c143f1ef387b42f4684574e0ffd04593caad122 [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 Stinner7ddd56f2018-11-14 00:24:28 +0100301static int
302dump_config_impl(void)
Victor Stinner56b29b62018-07-26 18:57:56 +0200303{
Victor Stinner7ddd56f2018-11-14 00:24:28 +0100304 PyObject *config = NULL;
305 PyObject *dict = NULL;
306
307 config = PyDict_New();
308 if (config == NULL) {
309 goto error;
Victor Stinner56b29b62018-07-26 18:57:56 +0200310 }
311
Victor Stinner7ddd56f2018-11-14 00:24:28 +0100312 /* global config */
313 dict = _Py_GetGlobalVariablesAsDict();
314 if (dict == NULL) {
315 goto error;
316 }
317 if (PyDict_SetItemString(config, "global_config", dict) < 0) {
318 goto error;
319 }
320 Py_CLEAR(dict);
321
322 /* core config */
Victor Stinnercaba55b2018-08-03 15:33:52 +0200323 PyInterpreterState *interp = _PyInterpreterState_Get();
Eric Snowbe3b2952019-02-23 11:35:52 -0700324 const _PyCoreConfig *core_config = _PyInterpreterState_GetCoreConfig(interp);
Victor Stinner7ddd56f2018-11-14 00:24:28 +0100325 dict = _PyCoreConfig_AsDict(core_config);
326 if (dict == NULL) {
327 goto error;
Victor Stinnerea68d832018-08-01 03:07:18 +0200328 }
Victor Stinner7ddd56f2018-11-14 00:24:28 +0100329 if (PyDict_SetItemString(config, "core_config", dict) < 0) {
330 goto error;
331 }
332 Py_CLEAR(dict);
Victor Stinnerea68d832018-08-01 03:07:18 +0200333
Victor Stinner7ddd56f2018-11-14 00:24:28 +0100334 /* main config */
Eric Snowbe3b2952019-02-23 11:35:52 -0700335 const _PyMainInterpreterConfig *main_config = _PyInterpreterState_GetMainConfig(interp);
Victor Stinner7ddd56f2018-11-14 00:24:28 +0100336 dict = _PyMainInterpreterConfig_AsDict(main_config);
337 if (dict == NULL) {
338 goto error;
339 }
340 if (PyDict_SetItemString(config, "main_config", dict) < 0) {
341 goto error;
342 }
343 Py_CLEAR(dict);
Victor Stinner56b29b62018-07-26 18:57:56 +0200344
Victor Stinner7ddd56f2018-11-14 00:24:28 +0100345 PyObject *json = PyImport_ImportModule("json");
346 PyObject *res = PyObject_CallMethod(json, "dumps", "O", config);
347 Py_DECREF(json);
348 Py_CLEAR(config);
349 if (res == NULL) {
350 goto error;
351 }
Victor Stinner5a953fd2018-08-03 22:49:07 +0200352
Victor Stinner7ddd56f2018-11-14 00:24:28 +0100353 PySys_FormatStdout("%S\n", res);
354 Py_DECREF(res);
Victor Stinner56b29b62018-07-26 18:57:56 +0200355
Victor Stinner7ddd56f2018-11-14 00:24:28 +0100356 return 0;
Victor Stinner56b29b62018-07-26 18:57:56 +0200357
Victor Stinner7ddd56f2018-11-14 00:24:28 +0100358error:
359 Py_XDECREF(config);
360 Py_XDECREF(dict);
361 return -1;
Victor Stinner56b29b62018-07-26 18:57:56 +0200362}
363
Victor Stinner01de89c2018-11-14 17:39:45 +0100364
Victor Stinner00b137c2018-11-13 19:59:26 +0100365static void
366dump_config(void)
367{
Victor Stinner7ddd56f2018-11-14 00:24:28 +0100368 if (dump_config_impl() < 0) {
369 fprintf(stderr, "failed to dump the configuration:\n");
370 PyErr_Print();
371 }
Victor Stinner00b137c2018-11-13 19:59:26 +0100372}
373
374
Victor Stinner56b29b62018-07-26 18:57:56 +0200375static int test_init_default_config(void)
376{
377 _testembed_Py_Initialize();
378 dump_config();
379 Py_Finalize();
380 return 0;
381}
382
383
384static int test_init_global_config(void)
385{
386 /* FIXME: test Py_IgnoreEnvironmentFlag */
387
388 putenv("PYTHONUTF8=0");
389 Py_UTF8Mode = 1;
390
391 /* Test initialization from global configuration variables (Py_xxx) */
392 Py_SetProgramName(L"./globalvar");
393
394 /* Py_IsolatedFlag is not tested */
395 Py_NoSiteFlag = 1;
396 Py_BytesWarningFlag = 1;
397
398 putenv("PYTHONINSPECT=");
399 Py_InspectFlag = 1;
400
401 putenv("PYTHONOPTIMIZE=0");
402 Py_InteractiveFlag = 1;
403
404 putenv("PYTHONDEBUG=0");
405 Py_OptimizeFlag = 2;
406
407 /* Py_DebugFlag is not tested */
408
409 putenv("PYTHONDONTWRITEBYTECODE=");
410 Py_DontWriteBytecodeFlag = 1;
411
412 putenv("PYTHONVERBOSE=0");
413 Py_VerboseFlag = 1;
414
415 Py_QuietFlag = 1;
416 Py_NoUserSiteDirectory = 1;
417
418 putenv("PYTHONUNBUFFERED=");
419 Py_UnbufferedStdioFlag = 1;
420
Victor Stinnerb75d7e22018-08-01 02:13:04 +0200421 Py_FrozenFlag = 1;
422
Victor Stinner56b29b62018-07-26 18:57:56 +0200423 /* FIXME: test Py_LegacyWindowsFSEncodingFlag */
424 /* FIXME: test Py_LegacyWindowsStdioFlag */
425
Victor Stinner56b29b62018-07-26 18:57:56 +0200426 Py_Initialize();
427 dump_config();
428 Py_Finalize();
429 return 0;
430}
431
432
433static int test_init_from_config(void)
434{
435 /* Test _Py_InitializeFromConfig() */
436 _PyCoreConfig config = _PyCoreConfig_INIT;
437 config.install_signal_handlers = 0;
438
439 /* FIXME: test use_environment */
440
441 putenv("PYTHONHASHSEED=42");
442 config.use_hash_seed = 1;
443 config.hash_seed = 123;
444
Victor Stinner25d13f32019-03-06 12:51:53 +0100445 putenv("PYTHONMALLOC=malloc_debug");
446 config.preconfig.allocator = "malloc";
Victor Stinner56b29b62018-07-26 18:57:56 +0200447
448 /* dev_mode=1 is tested in test_init_dev_mode() */
449
450 putenv("PYTHONFAULTHANDLER=");
451 config.faulthandler = 1;
452
453 putenv("PYTHONTRACEMALLOC=0");
454 config.tracemalloc = 2;
455
456 putenv("PYTHONPROFILEIMPORTTIME=0");
457 config.import_time = 1;
458
459 config.show_ref_count = 1;
460 config.show_alloc_count = 1;
461 /* FIXME: test dump_refs: bpo-34223 */
462
463 putenv("PYTHONMALLOCSTATS=0");
464 config.malloc_stats = 1;
465
Victor Stinner06e76082018-09-19 14:56:36 -0700466 /* FIXME: test coerce_c_locale and coerce_c_locale_warn */
467
Victor Stinner56b29b62018-07-26 18:57:56 +0200468 putenv("PYTHONUTF8=0");
469 Py_UTF8Mode = 0;
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100470 config.preconfig.utf8_mode = 1;
Victor Stinner56b29b62018-07-26 18:57:56 +0200471
472 putenv("PYTHONPYCACHEPREFIX=env_pycache_prefix");
473 config.pycache_prefix = L"conf_pycache_prefix";
474
475 Py_SetProgramName(L"./globalvar");
476 config.program_name = L"./conf_program_name";
477
Victor Stinner01de89c2018-11-14 17:39:45 +0100478 static wchar_t* argv[2] = {
479 L"-c",
480 L"pass",
481 };
Victor Stinner74f65682019-03-15 15:08:05 +0100482 config.argv.length = Py_ARRAY_LENGTH(argv);
483 config.argv.items = argv;
Victor Stinner01de89c2018-11-14 17:39:45 +0100484
Victor Stinner56b29b62018-07-26 18:57:56 +0200485 config.program = L"conf_program";
Victor Stinner01de89c2018-11-14 17:39:45 +0100486
487 static wchar_t* xoptions[3] = {
488 L"core_xoption1=3",
489 L"core_xoption2=",
490 L"core_xoption3",
491 };
Victor Stinner74f65682019-03-15 15:08:05 +0100492 config.xoptions.length = Py_ARRAY_LENGTH(xoptions);
493 config.xoptions.items = xoptions;
Victor Stinner01de89c2018-11-14 17:39:45 +0100494
495 static wchar_t* warnoptions[2] = {
496 L"default",
497 L"error::ResourceWarning",
498 };
Victor Stinner74f65682019-03-15 15:08:05 +0100499 config.warnoptions.length = Py_ARRAY_LENGTH(warnoptions);
500 config.warnoptions.items = warnoptions;
Victor Stinner01de89c2018-11-14 17:39:45 +0100501
Victor Stinner56b29b62018-07-26 18:57:56 +0200502 /* FIXME: test module_search_path_env */
503 /* FIXME: test home */
504 /* FIXME: test path config: module_search_path .. dll_path */
505
506 putenv("PYTHONVERBOSE=0");
507 Py_VerboseFlag = 0;
508 config.verbose = 1;
509
510 Py_NoSiteFlag = 0;
511 config.site_import = 0;
512
513 Py_BytesWarningFlag = 0;
514 config.bytes_warning = 1;
515
516 putenv("PYTHONINSPECT=");
517 Py_InspectFlag = 0;
518 config.inspect = 1;
519
520 Py_InteractiveFlag = 0;
521 config.interactive = 1;
522
523 putenv("PYTHONOPTIMIZE=0");
524 Py_OptimizeFlag = 1;
525 config.optimization_level = 2;
526
Victor Stinner98512272018-08-01 03:07:00 +0200527 /* FIXME: test parser_debug */
Victor Stinner56b29b62018-07-26 18:57:56 +0200528
529 putenv("PYTHONDONTWRITEBYTECODE=");
530 Py_DontWriteBytecodeFlag = 0;
531 config.write_bytecode = 0;
532
533 Py_QuietFlag = 0;
534 config.quiet = 1;
535
536 putenv("PYTHONUNBUFFERED=");
537 Py_UnbufferedStdioFlag = 0;
Victor Stinner98512272018-08-01 03:07:00 +0200538 config.buffered_stdio = 0;
Victor Stinner56b29b62018-07-26 18:57:56 +0200539
Victor Stinnerdfe0dc72018-08-29 11:47:29 +0200540 putenv("PYTHONIOENCODING=cp424");
541 Py_SetStandardStreamEncoding("ascii", "ignore");
Victor Stinner01de89c2018-11-14 17:39:45 +0100542#ifdef MS_WINDOWS
543 /* Py_SetStandardStreamEncoding() sets Py_LegacyWindowsStdioFlag to 1.
544 Force it to 0 through the config. */
545 config.legacy_windows_stdio = 0;
546#endif
Victor Stinnerdfe0dc72018-08-29 11:47:29 +0200547 config.stdio_encoding = "iso8859-1";
548 config.stdio_errors = "replace";
549
Victor Stinner56b29b62018-07-26 18:57:56 +0200550 putenv("PYTHONNOUSERSITE=");
551 Py_NoUserSiteDirectory = 0;
552 config.user_site_directory = 0;
553
554 config._check_hash_pycs_mode = "always";
555
Victor Stinnerb75d7e22018-08-01 02:13:04 +0200556 Py_FrozenFlag = 0;
557 config._frozen = 1;
558
Victor Stinner56b29b62018-07-26 18:57:56 +0200559 _PyInitError err = _Py_InitializeFromConfig(&config);
560 /* Don't call _PyCoreConfig_Clear() since all strings are static */
561 if (_Py_INIT_FAILED(err)) {
Victor Stinnerdfe88472019-03-01 12:14:41 +0100562 _Py_ExitInitError(err);
Victor Stinner56b29b62018-07-26 18:57:56 +0200563 }
564 dump_config();
565 Py_Finalize();
566 return 0;
567}
568
569
570static void test_init_env_putenvs(void)
571{
572 putenv("PYTHONHASHSEED=42");
Victor Stinner25d13f32019-03-06 12:51:53 +0100573 putenv("PYTHONMALLOC=malloc");
Victor Stinner56b29b62018-07-26 18:57:56 +0200574 putenv("PYTHONTRACEMALLOC=2");
575 putenv("PYTHONPROFILEIMPORTTIME=1");
576 putenv("PYTHONMALLOCSTATS=1");
577 putenv("PYTHONUTF8=1");
578 putenv("PYTHONVERBOSE=1");
579 putenv("PYTHONINSPECT=1");
580 putenv("PYTHONOPTIMIZE=2");
581 putenv("PYTHONDONTWRITEBYTECODE=1");
582 putenv("PYTHONUNBUFFERED=1");
583 putenv("PYTHONPYCACHEPREFIX=env_pycache_prefix");
584 putenv("PYTHONNOUSERSITE=1");
585 putenv("PYTHONFAULTHANDLER=1");
Victor Stinnerdfe0dc72018-08-29 11:47:29 +0200586 putenv("PYTHONIOENCODING=iso8859-1:replace");
Victor Stinner56b29b62018-07-26 18:57:56 +0200587 /* FIXME: test PYTHONWARNINGS */
588 /* FIXME: test PYTHONEXECUTABLE */
589 /* FIXME: test PYTHONHOME */
590 /* FIXME: test PYTHONDEBUG */
591 /* FIXME: test PYTHONDUMPREFS */
592 /* FIXME: test PYTHONCOERCECLOCALE */
593 /* FIXME: test PYTHONPATH */
594}
595
596
597static int test_init_env(void)
598{
599 /* Test initialization from environment variables */
600 Py_IgnoreEnvironmentFlag = 0;
601 test_init_env_putenvs();
602 _testembed_Py_Initialize();
603 dump_config();
604 Py_Finalize();
605 return 0;
606}
607
608
Victor Stinner25d13f32019-03-06 12:51:53 +0100609static void test_init_env_dev_mode_putenvs(void)
610{
611 test_init_env_putenvs();
612 putenv("PYTHONMALLOC=");
613 putenv("PYTHONFAULTHANDLER=");
614 putenv("PYTHONDEVMODE=1");
615}
616
617
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100618static int test_init_env_dev_mode(void)
619{
620 /* Test initialization from environment variables */
621 Py_IgnoreEnvironmentFlag = 0;
622 test_init_env_dev_mode_putenvs();
623 _testembed_Py_Initialize();
624 dump_config();
625 Py_Finalize();
626 return 0;
627}
628
629
Victor Stinner25d13f32019-03-06 12:51:53 +0100630static int test_init_env_dev_mode_alloc(void)
631{
632 /* Test initialization from environment variables */
633 Py_IgnoreEnvironmentFlag = 0;
634 test_init_env_dev_mode_putenvs();
635 putenv("PYTHONMALLOC=malloc");
636 _testembed_Py_Initialize();
637 dump_config();
638 Py_Finalize();
639 return 0;
640}
641
642
Victor Stinner56b29b62018-07-26 18:57:56 +0200643static int test_init_isolated(void)
644{
645 /* Test _PyCoreConfig.isolated=1 */
646 _PyCoreConfig config = _PyCoreConfig_INIT;
647
Victor Stinnercad1f742019-03-05 02:01:27 +0100648 Py_IsolatedFlag = 0;
649 config.preconfig.isolated = 1;
650
Victor Stinner06e76082018-09-19 14:56:36 -0700651 /* Set coerce_c_locale and utf8_mode to not depend on the locale */
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100652 config.preconfig.coerce_c_locale = 0;
653 config.preconfig.utf8_mode = 0;
Victor Stinner56b29b62018-07-26 18:57:56 +0200654 /* Use path starting with "./" avoids a search along the PATH */
655 config.program_name = L"./_testembed";
656
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100657 test_init_env_dev_mode_putenvs();
Victor Stinner56b29b62018-07-26 18:57:56 +0200658 _PyInitError err = _Py_InitializeFromConfig(&config);
659 if (_Py_INIT_FAILED(err)) {
Victor Stinnerdfe88472019-03-01 12:14:41 +0100660 _Py_ExitInitError(err);
Victor Stinner56b29b62018-07-26 18:57:56 +0200661 }
662 dump_config();
663 Py_Finalize();
664 return 0;
665}
666
667
668static int test_init_dev_mode(void)
669{
670 _PyCoreConfig config = _PyCoreConfig_INIT;
671 putenv("PYTHONFAULTHANDLER=");
672 putenv("PYTHONMALLOC=");
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100673 config.preconfig.dev_mode = 1;
Victor Stinner56b29b62018-07-26 18:57:56 +0200674 config.program_name = L"./_testembed";
675 _PyInitError err = _Py_InitializeFromConfig(&config);
676 if (_Py_INIT_FAILED(err)) {
Victor Stinnerdfe88472019-03-01 12:14:41 +0100677 _Py_ExitInitError(err);
Victor Stinner56b29b62018-07-26 18:57:56 +0200678 }
679 dump_config();
680 Py_Finalize();
681 return 0;
682}
683
684
Steve Dowerea74f0c2017-01-01 20:25:03 -0800685/* *********************************************************
686 * List of test cases and the function that implements it.
Serhiy Storchaka13ad3b72017-09-14 09:38:36 +0300687 *
Steve Dowerea74f0c2017-01-01 20:25:03 -0800688 * Names are compared case-sensitively with the first
689 * argument. If no match is found, or no first argument was
690 * provided, the names of all test cases are printed and
691 * the exit code will be -1.
692 *
693 * The int returned from test functions is used as the exit
694 * code, and test_capi treats all non-zero exit codes as a
Serhiy Storchaka13ad3b72017-09-14 09:38:36 +0300695 * failed test.
Steve Dowerea74f0c2017-01-01 20:25:03 -0800696 *********************************************************/
697struct TestCase
698{
699 const char *name;
700 int (*func)(void);
701};
702
703static struct TestCase TestCases[] = {
704 { "forced_io_encoding", test_forced_io_encoding },
705 { "repeated_init_and_subinterpreters", test_repeated_init_and_subinterpreters },
Victor Stinner9e87e772017-11-24 12:09:24 +0100706 { "pre_initialization_api", test_pre_initialization_api },
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000707 { "pre_initialization_sys_options", test_pre_initialization_sys_options },
Victor Stinnerb4d1e1f2017-11-30 22:05:00 +0100708 { "bpo20891", test_bpo20891 },
Victor Stinner209abf72018-06-22 19:14:51 +0200709 { "initialize_twice", test_initialize_twice },
Victor Stinnerfb47bca2018-07-20 17:34:23 +0200710 { "initialize_pymain", test_initialize_pymain },
Victor Stinner56b29b62018-07-26 18:57:56 +0200711 { "init_default_config", test_init_default_config },
712 { "init_global_config", test_init_global_config },
713 { "init_from_config", test_init_from_config },
714 { "init_env", test_init_env },
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100715 { "init_env_dev_mode", test_init_env_dev_mode },
Victor Stinner25d13f32019-03-06 12:51:53 +0100716 { "init_env_dev_mode_alloc", test_init_env_dev_mode_alloc },
Victor Stinner56b29b62018-07-26 18:57:56 +0200717 { "init_dev_mode", test_init_dev_mode },
718 { "init_isolated", test_init_isolated },
Steve Dowerea74f0c2017-01-01 20:25:03 -0800719 { NULL, NULL }
720};
721
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000722int main(int argc, char *argv[])
723{
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000724 if (argc > 1) {
Steve Dowerea74f0c2017-01-01 20:25:03 -0800725 for (struct TestCase *tc = TestCases; tc && tc->name; tc++) {
726 if (strcmp(argv[1], tc->name) == 0)
727 return (*tc->func)();
728 }
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000729 }
Steve Dowerea74f0c2017-01-01 20:25:03 -0800730
731 /* No match found, or no test name provided, so display usage */
732 printf("Python " PY_VERSION " _testembed executable for embedded interpreter tests\n"
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000733 "Normally executed via 'EmbeddingTests' in Lib/test/test_embed.py\n\n"
Steve Dowerea74f0c2017-01-01 20:25:03 -0800734 "Usage: %s TESTNAME\n\nAll available tests:\n", argv[0]);
735 for (struct TestCase *tc = TestCases; tc && tc->name; tc++) {
736 printf(" %s\n", tc->name);
737 }
738
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000739 /* Non-zero exit code will cause test_embed.py tests to fail.
Steve Dowerea74f0c2017-01-01 20:25:03 -0800740 This is intentional. */
741 return -1;
Antoine Pitrou8e605772011-04-25 21:21:07 +0200742}