blob: ab5802da36303d36fb47158338d461e823dcffb9 [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 Stinner1075d162019-03-25 23:19:57 +0100304 PyObject *config = _Py_GetConfigsAsDict();
Victor Stinner7ddd56f2018-11-14 00:24:28 +0100305 if (config == NULL) {
Victor Stinner1075d162019-03-25 23:19:57 +0100306 return -1;
Victor Stinner56b29b62018-07-26 18:57:56 +0200307 }
308
Victor Stinner1075d162019-03-25 23:19:57 +0100309 PyObject *res;
Victor Stinner7ddd56f2018-11-14 00:24:28 +0100310 PyObject *json = PyImport_ImportModule("json");
Victor Stinner1075d162019-03-25 23:19:57 +0100311 if (json) {
312 res = PyObject_CallMethod(json, "dumps", "O", config);
313 Py_DECREF(json);
314 }
315 else {
316 res = NULL;
317 }
Victor Stinner7ddd56f2018-11-14 00:24:28 +0100318 Py_CLEAR(config);
319 if (res == NULL) {
Victor Stinner1075d162019-03-25 23:19:57 +0100320 return -1;
Victor Stinner7ddd56f2018-11-14 00:24:28 +0100321 }
Victor Stinner5a953fd2018-08-03 22:49:07 +0200322
Victor Stinner7ddd56f2018-11-14 00:24:28 +0100323 PySys_FormatStdout("%S\n", res);
324 Py_DECREF(res);
Victor Stinner56b29b62018-07-26 18:57:56 +0200325
Victor Stinner7ddd56f2018-11-14 00:24:28 +0100326 return 0;
Victor Stinner56b29b62018-07-26 18:57:56 +0200327}
328
Victor Stinner01de89c2018-11-14 17:39:45 +0100329
Victor Stinner00b137c2018-11-13 19:59:26 +0100330static void
331dump_config(void)
332{
Victor Stinner7ddd56f2018-11-14 00:24:28 +0100333 if (dump_config_impl() < 0) {
334 fprintf(stderr, "failed to dump the configuration:\n");
335 PyErr_Print();
336 }
Victor Stinner00b137c2018-11-13 19:59:26 +0100337}
338
339
Victor Stinner56b29b62018-07-26 18:57:56 +0200340static int test_init_default_config(void)
341{
342 _testembed_Py_Initialize();
343 dump_config();
344 Py_Finalize();
345 return 0;
346}
347
348
349static int test_init_global_config(void)
350{
351 /* FIXME: test Py_IgnoreEnvironmentFlag */
352
353 putenv("PYTHONUTF8=0");
354 Py_UTF8Mode = 1;
355
356 /* Test initialization from global configuration variables (Py_xxx) */
357 Py_SetProgramName(L"./globalvar");
358
359 /* Py_IsolatedFlag is not tested */
360 Py_NoSiteFlag = 1;
361 Py_BytesWarningFlag = 1;
362
363 putenv("PYTHONINSPECT=");
364 Py_InspectFlag = 1;
365
366 putenv("PYTHONOPTIMIZE=0");
367 Py_InteractiveFlag = 1;
368
369 putenv("PYTHONDEBUG=0");
370 Py_OptimizeFlag = 2;
371
372 /* Py_DebugFlag is not tested */
373
374 putenv("PYTHONDONTWRITEBYTECODE=");
375 Py_DontWriteBytecodeFlag = 1;
376
377 putenv("PYTHONVERBOSE=0");
378 Py_VerboseFlag = 1;
379
380 Py_QuietFlag = 1;
381 Py_NoUserSiteDirectory = 1;
382
383 putenv("PYTHONUNBUFFERED=");
384 Py_UnbufferedStdioFlag = 1;
385
Victor Stinnerb75d7e22018-08-01 02:13:04 +0200386 Py_FrozenFlag = 1;
387
Victor Stinner56b29b62018-07-26 18:57:56 +0200388 /* FIXME: test Py_LegacyWindowsFSEncodingFlag */
389 /* FIXME: test Py_LegacyWindowsStdioFlag */
390
Victor Stinner56b29b62018-07-26 18:57:56 +0200391 Py_Initialize();
392 dump_config();
393 Py_Finalize();
394 return 0;
395}
396
397
398static int test_init_from_config(void)
399{
400 /* Test _Py_InitializeFromConfig() */
401 _PyCoreConfig config = _PyCoreConfig_INIT;
402 config.install_signal_handlers = 0;
403
404 /* FIXME: test use_environment */
405
406 putenv("PYTHONHASHSEED=42");
407 config.use_hash_seed = 1;
408 config.hash_seed = 123;
409
Victor Stinner25d13f32019-03-06 12:51:53 +0100410 putenv("PYTHONMALLOC=malloc_debug");
411 config.preconfig.allocator = "malloc";
Victor Stinner56b29b62018-07-26 18:57:56 +0200412
413 /* dev_mode=1 is tested in test_init_dev_mode() */
414
415 putenv("PYTHONFAULTHANDLER=");
416 config.faulthandler = 1;
417
418 putenv("PYTHONTRACEMALLOC=0");
419 config.tracemalloc = 2;
420
421 putenv("PYTHONPROFILEIMPORTTIME=0");
422 config.import_time = 1;
423
424 config.show_ref_count = 1;
425 config.show_alloc_count = 1;
426 /* FIXME: test dump_refs: bpo-34223 */
427
428 putenv("PYTHONMALLOCSTATS=0");
429 config.malloc_stats = 1;
430
Victor Stinner06e76082018-09-19 14:56:36 -0700431 /* FIXME: test coerce_c_locale and coerce_c_locale_warn */
432
Victor Stinner56b29b62018-07-26 18:57:56 +0200433 putenv("PYTHONUTF8=0");
434 Py_UTF8Mode = 0;
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100435 config.preconfig.utf8_mode = 1;
Victor Stinner56b29b62018-07-26 18:57:56 +0200436
437 putenv("PYTHONPYCACHEPREFIX=env_pycache_prefix");
438 config.pycache_prefix = L"conf_pycache_prefix";
439
440 Py_SetProgramName(L"./globalvar");
441 config.program_name = L"./conf_program_name";
442
Victor Stinner01de89c2018-11-14 17:39:45 +0100443 static wchar_t* argv[2] = {
444 L"-c",
445 L"pass",
446 };
Victor Stinner74f65682019-03-15 15:08:05 +0100447 config.argv.length = Py_ARRAY_LENGTH(argv);
448 config.argv.items = argv;
Victor Stinner01de89c2018-11-14 17:39:45 +0100449
Victor Stinner56b29b62018-07-26 18:57:56 +0200450 config.program = L"conf_program";
Victor Stinner01de89c2018-11-14 17:39:45 +0100451
452 static wchar_t* xoptions[3] = {
453 L"core_xoption1=3",
454 L"core_xoption2=",
455 L"core_xoption3",
456 };
Victor Stinner74f65682019-03-15 15:08:05 +0100457 config.xoptions.length = Py_ARRAY_LENGTH(xoptions);
458 config.xoptions.items = xoptions;
Victor Stinner01de89c2018-11-14 17:39:45 +0100459
460 static wchar_t* warnoptions[2] = {
461 L"default",
462 L"error::ResourceWarning",
463 };
Victor Stinner74f65682019-03-15 15:08:05 +0100464 config.warnoptions.length = Py_ARRAY_LENGTH(warnoptions);
465 config.warnoptions.items = warnoptions;
Victor Stinner01de89c2018-11-14 17:39:45 +0100466
Victor Stinner56b29b62018-07-26 18:57:56 +0200467 /* FIXME: test module_search_path_env */
468 /* FIXME: test home */
469 /* FIXME: test path config: module_search_path .. dll_path */
470
471 putenv("PYTHONVERBOSE=0");
472 Py_VerboseFlag = 0;
473 config.verbose = 1;
474
475 Py_NoSiteFlag = 0;
476 config.site_import = 0;
477
478 Py_BytesWarningFlag = 0;
479 config.bytes_warning = 1;
480
481 putenv("PYTHONINSPECT=");
482 Py_InspectFlag = 0;
483 config.inspect = 1;
484
485 Py_InteractiveFlag = 0;
486 config.interactive = 1;
487
488 putenv("PYTHONOPTIMIZE=0");
489 Py_OptimizeFlag = 1;
490 config.optimization_level = 2;
491
Victor Stinner98512272018-08-01 03:07:00 +0200492 /* FIXME: test parser_debug */
Victor Stinner56b29b62018-07-26 18:57:56 +0200493
494 putenv("PYTHONDONTWRITEBYTECODE=");
495 Py_DontWriteBytecodeFlag = 0;
496 config.write_bytecode = 0;
497
498 Py_QuietFlag = 0;
499 config.quiet = 1;
500
501 putenv("PYTHONUNBUFFERED=");
502 Py_UnbufferedStdioFlag = 0;
Victor Stinner98512272018-08-01 03:07:00 +0200503 config.buffered_stdio = 0;
Victor Stinner56b29b62018-07-26 18:57:56 +0200504
Victor Stinnerdfe0dc72018-08-29 11:47:29 +0200505 putenv("PYTHONIOENCODING=cp424");
506 Py_SetStandardStreamEncoding("ascii", "ignore");
Victor Stinner01de89c2018-11-14 17:39:45 +0100507#ifdef MS_WINDOWS
508 /* Py_SetStandardStreamEncoding() sets Py_LegacyWindowsStdioFlag to 1.
509 Force it to 0 through the config. */
510 config.legacy_windows_stdio = 0;
511#endif
Victor Stinnerdfe0dc72018-08-29 11:47:29 +0200512 config.stdio_encoding = "iso8859-1";
513 config.stdio_errors = "replace";
514
Victor Stinner56b29b62018-07-26 18:57:56 +0200515 putenv("PYTHONNOUSERSITE=");
516 Py_NoUserSiteDirectory = 0;
517 config.user_site_directory = 0;
518
519 config._check_hash_pycs_mode = "always";
520
Victor Stinnerb75d7e22018-08-01 02:13:04 +0200521 Py_FrozenFlag = 0;
522 config._frozen = 1;
523
Victor Stinner56b29b62018-07-26 18:57:56 +0200524 _PyInitError err = _Py_InitializeFromConfig(&config);
525 /* Don't call _PyCoreConfig_Clear() since all strings are static */
526 if (_Py_INIT_FAILED(err)) {
Victor Stinnerdfe88472019-03-01 12:14:41 +0100527 _Py_ExitInitError(err);
Victor Stinner56b29b62018-07-26 18:57:56 +0200528 }
529 dump_config();
530 Py_Finalize();
531 return 0;
532}
533
534
535static void test_init_env_putenvs(void)
536{
537 putenv("PYTHONHASHSEED=42");
Victor Stinner25d13f32019-03-06 12:51:53 +0100538 putenv("PYTHONMALLOC=malloc");
Victor Stinner56b29b62018-07-26 18:57:56 +0200539 putenv("PYTHONTRACEMALLOC=2");
540 putenv("PYTHONPROFILEIMPORTTIME=1");
541 putenv("PYTHONMALLOCSTATS=1");
542 putenv("PYTHONUTF8=1");
543 putenv("PYTHONVERBOSE=1");
544 putenv("PYTHONINSPECT=1");
545 putenv("PYTHONOPTIMIZE=2");
546 putenv("PYTHONDONTWRITEBYTECODE=1");
547 putenv("PYTHONUNBUFFERED=1");
548 putenv("PYTHONPYCACHEPREFIX=env_pycache_prefix");
549 putenv("PYTHONNOUSERSITE=1");
550 putenv("PYTHONFAULTHANDLER=1");
Victor Stinnerdfe0dc72018-08-29 11:47:29 +0200551 putenv("PYTHONIOENCODING=iso8859-1:replace");
Victor Stinner56b29b62018-07-26 18:57:56 +0200552 /* FIXME: test PYTHONWARNINGS */
553 /* FIXME: test PYTHONEXECUTABLE */
554 /* FIXME: test PYTHONHOME */
555 /* FIXME: test PYTHONDEBUG */
556 /* FIXME: test PYTHONDUMPREFS */
557 /* FIXME: test PYTHONCOERCECLOCALE */
558 /* FIXME: test PYTHONPATH */
559}
560
561
562static int test_init_env(void)
563{
564 /* Test initialization from environment variables */
565 Py_IgnoreEnvironmentFlag = 0;
566 test_init_env_putenvs();
567 _testembed_Py_Initialize();
568 dump_config();
569 Py_Finalize();
570 return 0;
571}
572
573
Victor Stinner25d13f32019-03-06 12:51:53 +0100574static void test_init_env_dev_mode_putenvs(void)
575{
576 test_init_env_putenvs();
577 putenv("PYTHONMALLOC=");
578 putenv("PYTHONFAULTHANDLER=");
579 putenv("PYTHONDEVMODE=1");
580}
581
582
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100583static int test_init_env_dev_mode(void)
584{
585 /* Test initialization from environment variables */
586 Py_IgnoreEnvironmentFlag = 0;
587 test_init_env_dev_mode_putenvs();
588 _testembed_Py_Initialize();
589 dump_config();
590 Py_Finalize();
591 return 0;
592}
593
594
Victor Stinner25d13f32019-03-06 12:51:53 +0100595static int test_init_env_dev_mode_alloc(void)
596{
597 /* Test initialization from environment variables */
598 Py_IgnoreEnvironmentFlag = 0;
599 test_init_env_dev_mode_putenvs();
600 putenv("PYTHONMALLOC=malloc");
601 _testembed_Py_Initialize();
602 dump_config();
603 Py_Finalize();
604 return 0;
605}
606
607
Victor Stinner56b29b62018-07-26 18:57:56 +0200608static int test_init_isolated(void)
609{
610 /* Test _PyCoreConfig.isolated=1 */
611 _PyCoreConfig config = _PyCoreConfig_INIT;
612
Victor Stinnercad1f742019-03-05 02:01:27 +0100613 Py_IsolatedFlag = 0;
614 config.preconfig.isolated = 1;
615
Victor Stinner06e76082018-09-19 14:56:36 -0700616 /* Set coerce_c_locale and utf8_mode to not depend on the locale */
Victor Stinner5a02e0d2019-03-05 12:32:09 +0100617 config.preconfig.coerce_c_locale = 0;
618 config.preconfig.utf8_mode = 0;
Victor Stinner56b29b62018-07-26 18:57:56 +0200619 /* Use path starting with "./" avoids a search along the PATH */
620 config.program_name = L"./_testembed";
621
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100622 test_init_env_dev_mode_putenvs();
Victor Stinner56b29b62018-07-26 18:57:56 +0200623 _PyInitError err = _Py_InitializeFromConfig(&config);
624 if (_Py_INIT_FAILED(err)) {
Victor Stinnerdfe88472019-03-01 12:14:41 +0100625 _Py_ExitInitError(err);
Victor Stinner56b29b62018-07-26 18:57:56 +0200626 }
627 dump_config();
628 Py_Finalize();
629 return 0;
630}
631
632
633static int test_init_dev_mode(void)
634{
635 _PyCoreConfig config = _PyCoreConfig_INIT;
636 putenv("PYTHONFAULTHANDLER=");
637 putenv("PYTHONMALLOC=");
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100638 config.preconfig.dev_mode = 1;
Victor Stinner56b29b62018-07-26 18:57:56 +0200639 config.program_name = L"./_testembed";
640 _PyInitError err = _Py_InitializeFromConfig(&config);
641 if (_Py_INIT_FAILED(err)) {
Victor Stinnerdfe88472019-03-01 12:14:41 +0100642 _Py_ExitInitError(err);
Victor Stinner56b29b62018-07-26 18:57:56 +0200643 }
644 dump_config();
645 Py_Finalize();
646 return 0;
647}
648
649
Steve Dowerea74f0c2017-01-01 20:25:03 -0800650/* *********************************************************
651 * List of test cases and the function that implements it.
Serhiy Storchaka13ad3b72017-09-14 09:38:36 +0300652 *
Steve Dowerea74f0c2017-01-01 20:25:03 -0800653 * Names are compared case-sensitively with the first
654 * argument. If no match is found, or no first argument was
655 * provided, the names of all test cases are printed and
656 * the exit code will be -1.
657 *
658 * The int returned from test functions is used as the exit
659 * code, and test_capi treats all non-zero exit codes as a
Serhiy Storchaka13ad3b72017-09-14 09:38:36 +0300660 * failed test.
Steve Dowerea74f0c2017-01-01 20:25:03 -0800661 *********************************************************/
662struct TestCase
663{
664 const char *name;
665 int (*func)(void);
666};
667
668static struct TestCase TestCases[] = {
669 { "forced_io_encoding", test_forced_io_encoding },
670 { "repeated_init_and_subinterpreters", test_repeated_init_and_subinterpreters },
Victor Stinner9e87e772017-11-24 12:09:24 +0100671 { "pre_initialization_api", test_pre_initialization_api },
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000672 { "pre_initialization_sys_options", test_pre_initialization_sys_options },
Victor Stinnerb4d1e1f2017-11-30 22:05:00 +0100673 { "bpo20891", test_bpo20891 },
Victor Stinner209abf72018-06-22 19:14:51 +0200674 { "initialize_twice", test_initialize_twice },
Victor Stinnerfb47bca2018-07-20 17:34:23 +0200675 { "initialize_pymain", test_initialize_pymain },
Victor Stinner56b29b62018-07-26 18:57:56 +0200676 { "init_default_config", test_init_default_config },
677 { "init_global_config", test_init_global_config },
678 { "init_from_config", test_init_from_config },
679 { "init_env", test_init_env },
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100680 { "init_env_dev_mode", test_init_env_dev_mode },
Victor Stinner25d13f32019-03-06 12:51:53 +0100681 { "init_env_dev_mode_alloc", test_init_env_dev_mode_alloc },
Victor Stinner56b29b62018-07-26 18:57:56 +0200682 { "init_dev_mode", test_init_dev_mode },
683 { "init_isolated", test_init_isolated },
Steve Dowerea74f0c2017-01-01 20:25:03 -0800684 { NULL, NULL }
685};
686
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000687int main(int argc, char *argv[])
688{
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000689 if (argc > 1) {
Steve Dowerea74f0c2017-01-01 20:25:03 -0800690 for (struct TestCase *tc = TestCases; tc && tc->name; tc++) {
691 if (strcmp(argv[1], tc->name) == 0)
692 return (*tc->func)();
693 }
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000694 }
Steve Dowerea74f0c2017-01-01 20:25:03 -0800695
696 /* No match found, or no test name provided, so display usage */
697 printf("Python " PY_VERSION " _testembed executable for embedded interpreter tests\n"
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000698 "Normally executed via 'EmbeddingTests' in Lib/test/test_embed.py\n\n"
Steve Dowerea74f0c2017-01-01 20:25:03 -0800699 "Usage: %s TESTNAME\n\nAll available tests:\n", argv[0]);
700 for (struct TestCase *tc = TestCases; tc && tc->name; tc++) {
701 printf(" %s\n", tc->name);
702 }
703
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000704 /* Non-zero exit code will cause test_embed.py tests to fail.
Steve Dowerea74f0c2017-01-01 20:25:03 -0800705 This is intentional. */
706 return -1;
Antoine Pitrou8e605772011-04-25 21:21:07 +0200707}