blob: 7d71a961602d62ef08f956ceb088d2269caca513 [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{
Victor Stinner20004952019-03-26 02:31:11 +0100400 _PyInitError err;
401
402 _PyPreConfig preconfig = _PyPreConfig_INIT;
403
404 putenv("PYTHONMALLOC=malloc_debug");
405 preconfig.allocator = "malloc";
406
407 putenv("PYTHONUTF8=0");
408 Py_UTF8Mode = 0;
409 preconfig.utf8_mode = 1;
410
Victor Stinner5ac27a52019-03-27 13:40:14 +0100411 err = _Py_PreInitialize(&preconfig);
Victor Stinner20004952019-03-26 02:31:11 +0100412 if (_Py_INIT_FAILED(err)) {
413 _Py_ExitInitError(err);
414 }
415
Victor Stinner56b29b62018-07-26 18:57:56 +0200416 /* Test _Py_InitializeFromConfig() */
417 _PyCoreConfig config = _PyCoreConfig_INIT;
418 config.install_signal_handlers = 0;
419
420 /* FIXME: test use_environment */
421
422 putenv("PYTHONHASHSEED=42");
423 config.use_hash_seed = 1;
424 config.hash_seed = 123;
425
Victor Stinner56b29b62018-07-26 18:57:56 +0200426 /* dev_mode=1 is tested in test_init_dev_mode() */
427
428 putenv("PYTHONFAULTHANDLER=");
429 config.faulthandler = 1;
430
431 putenv("PYTHONTRACEMALLOC=0");
432 config.tracemalloc = 2;
433
434 putenv("PYTHONPROFILEIMPORTTIME=0");
435 config.import_time = 1;
436
437 config.show_ref_count = 1;
438 config.show_alloc_count = 1;
439 /* FIXME: test dump_refs: bpo-34223 */
440
441 putenv("PYTHONMALLOCSTATS=0");
442 config.malloc_stats = 1;
443
Victor Stinner56b29b62018-07-26 18:57:56 +0200444 putenv("PYTHONPYCACHEPREFIX=env_pycache_prefix");
445 config.pycache_prefix = L"conf_pycache_prefix";
446
447 Py_SetProgramName(L"./globalvar");
448 config.program_name = L"./conf_program_name";
449
Victor Stinner2f549082019-03-29 15:13:46 +0100450 static wchar_t* argv[] = {
451 L"python3",
Victor Stinner01de89c2018-11-14 17:39:45 +0100452 L"-c",
453 L"pass",
Victor Stinner2f549082019-03-29 15:13:46 +0100454 L"arg2",
Victor Stinner01de89c2018-11-14 17:39:45 +0100455 };
Victor Stinner74f65682019-03-15 15:08:05 +0100456 config.argv.length = Py_ARRAY_LENGTH(argv);
457 config.argv.items = argv;
Victor Stinner01de89c2018-11-14 17:39:45 +0100458
Victor Stinner56b29b62018-07-26 18:57:56 +0200459 config.program = L"conf_program";
Victor Stinner01de89c2018-11-14 17:39:45 +0100460
461 static wchar_t* xoptions[3] = {
462 L"core_xoption1=3",
463 L"core_xoption2=",
464 L"core_xoption3",
465 };
Victor Stinner74f65682019-03-15 15:08:05 +0100466 config.xoptions.length = Py_ARRAY_LENGTH(xoptions);
467 config.xoptions.items = xoptions;
Victor Stinner01de89c2018-11-14 17:39:45 +0100468
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100469 static wchar_t* warnoptions[1] = {
Victor Stinner01de89c2018-11-14 17:39:45 +0100470 L"error::ResourceWarning",
471 };
Victor Stinner74f65682019-03-15 15:08:05 +0100472 config.warnoptions.length = Py_ARRAY_LENGTH(warnoptions);
473 config.warnoptions.items = warnoptions;
Victor Stinner01de89c2018-11-14 17:39:45 +0100474
Victor Stinner56b29b62018-07-26 18:57:56 +0200475 /* FIXME: test module_search_path_env */
476 /* FIXME: test home */
477 /* FIXME: test path config: module_search_path .. dll_path */
478
479 putenv("PYTHONVERBOSE=0");
480 Py_VerboseFlag = 0;
481 config.verbose = 1;
482
483 Py_NoSiteFlag = 0;
484 config.site_import = 0;
485
486 Py_BytesWarningFlag = 0;
487 config.bytes_warning = 1;
488
489 putenv("PYTHONINSPECT=");
490 Py_InspectFlag = 0;
491 config.inspect = 1;
492
493 Py_InteractiveFlag = 0;
494 config.interactive = 1;
495
496 putenv("PYTHONOPTIMIZE=0");
497 Py_OptimizeFlag = 1;
498 config.optimization_level = 2;
499
Victor Stinner98512272018-08-01 03:07:00 +0200500 /* FIXME: test parser_debug */
Victor Stinner56b29b62018-07-26 18:57:56 +0200501
502 putenv("PYTHONDONTWRITEBYTECODE=");
503 Py_DontWriteBytecodeFlag = 0;
504 config.write_bytecode = 0;
505
506 Py_QuietFlag = 0;
507 config.quiet = 1;
508
509 putenv("PYTHONUNBUFFERED=");
510 Py_UnbufferedStdioFlag = 0;
Victor Stinner98512272018-08-01 03:07:00 +0200511 config.buffered_stdio = 0;
Victor Stinner56b29b62018-07-26 18:57:56 +0200512
Victor Stinnerdfe0dc72018-08-29 11:47:29 +0200513 putenv("PYTHONIOENCODING=cp424");
514 Py_SetStandardStreamEncoding("ascii", "ignore");
Victor Stinner01de89c2018-11-14 17:39:45 +0100515#ifdef MS_WINDOWS
516 /* Py_SetStandardStreamEncoding() sets Py_LegacyWindowsStdioFlag to 1.
517 Force it to 0 through the config. */
518 config.legacy_windows_stdio = 0;
519#endif
Victor Stinnerdfe0dc72018-08-29 11:47:29 +0200520 config.stdio_encoding = "iso8859-1";
521 config.stdio_errors = "replace";
522
Victor Stinner56b29b62018-07-26 18:57:56 +0200523 putenv("PYTHONNOUSERSITE=");
524 Py_NoUserSiteDirectory = 0;
525 config.user_site_directory = 0;
526
527 config._check_hash_pycs_mode = "always";
528
Victor Stinnerb75d7e22018-08-01 02:13:04 +0200529 Py_FrozenFlag = 0;
530 config._frozen = 1;
531
Victor Stinner5ac27a52019-03-27 13:40:14 +0100532 err = _Py_InitializeFromConfig(&config);
Victor Stinner56b29b62018-07-26 18:57:56 +0200533 if (_Py_INIT_FAILED(err)) {
Victor Stinnerdfe88472019-03-01 12:14:41 +0100534 _Py_ExitInitError(err);
Victor Stinner56b29b62018-07-26 18:57:56 +0200535 }
536 dump_config();
537 Py_Finalize();
538 return 0;
539}
540
541
542static void test_init_env_putenvs(void)
543{
544 putenv("PYTHONHASHSEED=42");
Victor Stinner25d13f32019-03-06 12:51:53 +0100545 putenv("PYTHONMALLOC=malloc");
Victor Stinner56b29b62018-07-26 18:57:56 +0200546 putenv("PYTHONTRACEMALLOC=2");
547 putenv("PYTHONPROFILEIMPORTTIME=1");
548 putenv("PYTHONMALLOCSTATS=1");
549 putenv("PYTHONUTF8=1");
550 putenv("PYTHONVERBOSE=1");
551 putenv("PYTHONINSPECT=1");
552 putenv("PYTHONOPTIMIZE=2");
553 putenv("PYTHONDONTWRITEBYTECODE=1");
554 putenv("PYTHONUNBUFFERED=1");
555 putenv("PYTHONPYCACHEPREFIX=env_pycache_prefix");
556 putenv("PYTHONNOUSERSITE=1");
557 putenv("PYTHONFAULTHANDLER=1");
Victor Stinnerdfe0dc72018-08-29 11:47:29 +0200558 putenv("PYTHONIOENCODING=iso8859-1:replace");
Victor Stinner56b29b62018-07-26 18:57:56 +0200559 /* FIXME: test PYTHONWARNINGS */
560 /* FIXME: test PYTHONEXECUTABLE */
561 /* FIXME: test PYTHONHOME */
562 /* FIXME: test PYTHONDEBUG */
563 /* FIXME: test PYTHONDUMPREFS */
564 /* FIXME: test PYTHONCOERCECLOCALE */
565 /* FIXME: test PYTHONPATH */
566}
567
568
569static int test_init_env(void)
570{
571 /* Test initialization from environment variables */
572 Py_IgnoreEnvironmentFlag = 0;
573 test_init_env_putenvs();
574 _testembed_Py_Initialize();
575 dump_config();
576 Py_Finalize();
577 return 0;
578}
579
580
Victor Stinner25d13f32019-03-06 12:51:53 +0100581static void test_init_env_dev_mode_putenvs(void)
582{
583 test_init_env_putenvs();
584 putenv("PYTHONMALLOC=");
585 putenv("PYTHONFAULTHANDLER=");
586 putenv("PYTHONDEVMODE=1");
587}
588
589
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100590static int test_init_env_dev_mode(void)
591{
592 /* Test initialization from environment variables */
593 Py_IgnoreEnvironmentFlag = 0;
594 test_init_env_dev_mode_putenvs();
595 _testembed_Py_Initialize();
596 dump_config();
597 Py_Finalize();
598 return 0;
599}
600
601
Victor Stinner25d13f32019-03-06 12:51:53 +0100602static int test_init_env_dev_mode_alloc(void)
603{
604 /* Test initialization from environment variables */
605 Py_IgnoreEnvironmentFlag = 0;
606 test_init_env_dev_mode_putenvs();
607 putenv("PYTHONMALLOC=malloc");
608 _testembed_Py_Initialize();
609 dump_config();
610 Py_Finalize();
611 return 0;
612}
613
614
Victor Stinner56b29b62018-07-26 18:57:56 +0200615static int test_init_isolated(void)
616{
Victor Stinner20004952019-03-26 02:31:11 +0100617 _PyInitError err;
618
Victor Stinner56b29b62018-07-26 18:57:56 +0200619 /* Test _PyCoreConfig.isolated=1 */
620 _PyCoreConfig config = _PyCoreConfig_INIT;
621
Victor Stinnercad1f742019-03-05 02:01:27 +0100622 Py_IsolatedFlag = 0;
Victor Stinner20004952019-03-26 02:31:11 +0100623 config.isolated = 1;
Victor Stinnercad1f742019-03-05 02:01:27 +0100624
Victor Stinner56b29b62018-07-26 18:57:56 +0200625 /* Use path starting with "./" avoids a search along the PATH */
626 config.program_name = L"./_testembed";
627
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100628 test_init_env_dev_mode_putenvs();
Victor Stinner5ac27a52019-03-27 13:40:14 +0100629 err = _Py_InitializeFromConfig(&config);
Victor Stinner56b29b62018-07-26 18:57:56 +0200630 if (_Py_INIT_FAILED(err)) {
Victor Stinnerdfe88472019-03-01 12:14:41 +0100631 _Py_ExitInitError(err);
Victor Stinner56b29b62018-07-26 18:57:56 +0200632 }
633 dump_config();
634 Py_Finalize();
635 return 0;
636}
637
638
Victor Stinner6da20a42019-03-27 00:26:18 +0100639/* _PyPreConfig.isolated=1, _PyCoreConfig.isolated=0 */
640static int test_preinit_isolated1(void)
641{
642 _PyInitError err;
643
644 _PyPreConfig preconfig = _PyPreConfig_INIT;
Victor Stinner6da20a42019-03-27 00:26:18 +0100645 preconfig.isolated = 1;
646
Victor Stinner5ac27a52019-03-27 13:40:14 +0100647 err = _Py_PreInitialize(&preconfig);
Victor Stinner6da20a42019-03-27 00:26:18 +0100648 if (_Py_INIT_FAILED(err)) {
649 _Py_ExitInitError(err);
650 }
651
652 _PyCoreConfig config = _PyCoreConfig_INIT;
653 config.program_name = L"./_testembed";
654
655 test_init_env_dev_mode_putenvs();
Victor Stinner5ac27a52019-03-27 13:40:14 +0100656 err = _Py_InitializeFromConfig(&config);
Victor Stinner6da20a42019-03-27 00:26:18 +0100657 if (_Py_INIT_FAILED(err)) {
658 _Py_ExitInitError(err);
659 }
660 dump_config();
661 Py_Finalize();
662 return 0;
663}
664
665
666/* _PyPreConfig.isolated=0, _PyCoreConfig.isolated=1 */
667static int test_preinit_isolated2(void)
668{
669 _PyInitError err;
670
671 _PyPreConfig preconfig = _PyPreConfig_INIT;
Victor Stinner6da20a42019-03-27 00:26:18 +0100672 preconfig.isolated = 0;
673
Victor Stinner5ac27a52019-03-27 13:40:14 +0100674 err = _Py_PreInitialize(&preconfig);
Victor Stinner6da20a42019-03-27 00:26:18 +0100675 if (_Py_INIT_FAILED(err)) {
676 _Py_ExitInitError(err);
677 }
678
679 /* Test _PyCoreConfig.isolated=1 */
680 _PyCoreConfig config = _PyCoreConfig_INIT;
681
682 Py_IsolatedFlag = 0;
683 config.isolated = 1;
684
685 /* Use path starting with "./" avoids a search along the PATH */
686 config.program_name = L"./_testembed";
687
688 test_init_env_dev_mode_putenvs();
Victor Stinner5ac27a52019-03-27 13:40:14 +0100689 err = _Py_InitializeFromConfig(&config);
Victor Stinner6da20a42019-03-27 00:26:18 +0100690 if (_Py_INIT_FAILED(err)) {
691 _Py_ExitInitError(err);
692 }
693 dump_config();
694 Py_Finalize();
695 return 0;
696}
697
698
Victor Stinner56b29b62018-07-26 18:57:56 +0200699static int test_init_dev_mode(void)
700{
701 _PyCoreConfig config = _PyCoreConfig_INIT;
702 putenv("PYTHONFAULTHANDLER=");
703 putenv("PYTHONMALLOC=");
Victor Stinner20004952019-03-26 02:31:11 +0100704 config.dev_mode = 1;
Victor Stinner56b29b62018-07-26 18:57:56 +0200705 config.program_name = L"./_testembed";
Victor Stinner5ac27a52019-03-27 13:40:14 +0100706 _PyInitError err = _Py_InitializeFromConfig(&config);
Victor Stinner56b29b62018-07-26 18:57:56 +0200707 if (_Py_INIT_FAILED(err)) {
Victor Stinnerdfe88472019-03-01 12:14:41 +0100708 _Py_ExitInitError(err);
Victor Stinner56b29b62018-07-26 18:57:56 +0200709 }
710 dump_config();
711 Py_Finalize();
712 return 0;
713}
714
715
Victor Stinner2f549082019-03-29 15:13:46 +0100716static int test_run_main(void)
717{
718 _PyCoreConfig config = _PyCoreConfig_INIT;
719
720 wchar_t *argv[] = {L"python3", L"-c",
721 (L"import sys; "
722 L"print(f'_Py_RunMain(): sys.argv={sys.argv}')"),
723 L"arg2"};
724 config.argv.length = Py_ARRAY_LENGTH(argv);
725 config.argv.items = argv;
726 config.program_name = L"./python3";
727
728 _PyInitError err = _Py_InitializeFromConfig(&config);
729 if (_Py_INIT_FAILED(err)) {
730 _Py_ExitInitError(err);
731 }
732
733 return _Py_RunMain();
734}
735
736
Steve Dowerea74f0c2017-01-01 20:25:03 -0800737/* *********************************************************
738 * List of test cases and the function that implements it.
Serhiy Storchaka13ad3b72017-09-14 09:38:36 +0300739 *
Steve Dowerea74f0c2017-01-01 20:25:03 -0800740 * Names are compared case-sensitively with the first
741 * argument. If no match is found, or no first argument was
742 * provided, the names of all test cases are printed and
743 * the exit code will be -1.
744 *
745 * The int returned from test functions is used as the exit
746 * code, and test_capi treats all non-zero exit codes as a
Serhiy Storchaka13ad3b72017-09-14 09:38:36 +0300747 * failed test.
Steve Dowerea74f0c2017-01-01 20:25:03 -0800748 *********************************************************/
749struct TestCase
750{
751 const char *name;
752 int (*func)(void);
753};
754
755static struct TestCase TestCases[] = {
756 { "forced_io_encoding", test_forced_io_encoding },
757 { "repeated_init_and_subinterpreters", test_repeated_init_and_subinterpreters },
Victor Stinner9e87e772017-11-24 12:09:24 +0100758 { "pre_initialization_api", test_pre_initialization_api },
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000759 { "pre_initialization_sys_options", test_pre_initialization_sys_options },
Victor Stinnerb4d1e1f2017-11-30 22:05:00 +0100760 { "bpo20891", test_bpo20891 },
Victor Stinner209abf72018-06-22 19:14:51 +0200761 { "initialize_twice", test_initialize_twice },
Victor Stinnerfb47bca2018-07-20 17:34:23 +0200762 { "initialize_pymain", test_initialize_pymain },
Victor Stinner56b29b62018-07-26 18:57:56 +0200763 { "init_default_config", test_init_default_config },
764 { "init_global_config", test_init_global_config },
765 { "init_from_config", test_init_from_config },
766 { "init_env", test_init_env },
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100767 { "init_env_dev_mode", test_init_env_dev_mode },
Victor Stinner25d13f32019-03-06 12:51:53 +0100768 { "init_env_dev_mode_alloc", test_init_env_dev_mode_alloc },
Victor Stinner56b29b62018-07-26 18:57:56 +0200769 { "init_dev_mode", test_init_dev_mode },
770 { "init_isolated", test_init_isolated },
Victor Stinner6da20a42019-03-27 00:26:18 +0100771 { "preinit_isolated1", test_preinit_isolated1 },
772 { "preinit_isolated2", test_preinit_isolated2 },
Victor Stinner2f549082019-03-29 15:13:46 +0100773 { "run_main", test_run_main },
Steve Dowerea74f0c2017-01-01 20:25:03 -0800774 { NULL, NULL }
775};
776
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000777int main(int argc, char *argv[])
778{
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000779 if (argc > 1) {
Steve Dowerea74f0c2017-01-01 20:25:03 -0800780 for (struct TestCase *tc = TestCases; tc && tc->name; tc++) {
781 if (strcmp(argv[1], tc->name) == 0)
782 return (*tc->func)();
783 }
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000784 }
Steve Dowerea74f0c2017-01-01 20:25:03 -0800785
786 /* No match found, or no test name provided, so display usage */
787 printf("Python " PY_VERSION " _testembed executable for embedded interpreter tests\n"
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000788 "Normally executed via 'EmbeddingTests' in Lib/test/test_embed.py\n\n"
Steve Dowerea74f0c2017-01-01 20:25:03 -0800789 "Usage: %s TESTNAME\n\nAll available tests:\n", argv[0]);
790 for (struct TestCase *tc = TestCases; tc && tc->name; tc++) {
791 printf(" %s\n", tc->name);
792 }
793
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000794 /* Non-zero exit code will cause test_embed.py tests to fail.
Steve Dowerea74f0c2017-01-01 20:25:03 -0800795 This is intentional. */
796 return -1;
Antoine Pitrou8e605772011-04-25 21:21:07 +0200797}