blob: 6e764e3b6cce57884c46a3342fc020b30f01a43a [file] [log] [blame]
Antoine Pitrou8e605772011-04-25 21:21:07 +02001#include <Python.h>
Victor Stinnerb4d1e1f2017-11-30 22:05:00 +01002#include "pythread.h"
Eric Snowe3774162017-05-22 19:46:40 -07003#include <inttypes.h>
Antoine Pitrou8e605772011-04-25 21:21:07 +02004#include <stdio.h>
Nick Coghlanbc77eff2018-03-25 20:44:30 +10005#include <wchar.h>
Antoine Pitrou8e605772011-04-25 21:21:07 +02006
Nick Coghlan7d270ee2013-10-17 22:35:35 +10007/*********************************************************
8 * Embedded interpreter tests that need a custom exe
9 *
10 * Executed via 'EmbeddingTests' in Lib/test/test_capi.py
11 *********************************************************/
12
13static void _testembed_Py_Initialize(void)
14{
15 /* HACK: the "./" at front avoids a search along the PATH in
16 Modules/getpath.c */
17 Py_SetProgramName(L"./_testembed");
18 Py_Initialize();
19}
20
21
22/*****************************************************
Martin Panter8f265652016-04-19 04:03:41 +000023 * Test repeated initialisation and subinterpreters
Nick Coghlan7d270ee2013-10-17 22:35:35 +100024 *****************************************************/
25
26static void print_subinterp(void)
Antoine Pitrou8e605772011-04-25 21:21:07 +020027{
Eric Snowe3774162017-05-22 19:46:40 -070028 /* Output information about the interpreter in the format
29 expected in Lib/test/test_capi.py (test_subinterps). */
Antoine Pitrou8e605772011-04-25 21:21:07 +020030 PyThreadState *ts = PyThreadState_Get();
Eric Snowe3774162017-05-22 19:46:40 -070031 PyInterpreterState *interp = ts->interp;
32 int64_t id = PyInterpreterState_GetID(interp);
Eric Snowd1c3c132017-05-24 17:19:47 -070033 printf("interp %" PRId64 " <0x%" PRIXPTR ">, thread state <0x%" PRIXPTR ">: ",
Eric Snowe3774162017-05-22 19:46:40 -070034 id, (uintptr_t)interp, (uintptr_t)ts);
Antoine Pitrou8e605772011-04-25 21:21:07 +020035 fflush(stdout);
36 PyRun_SimpleString(
37 "import sys;"
38 "print('id(modules) =', id(sys.modules));"
39 "sys.stdout.flush()"
40 );
41}
42
Steve Dowerea74f0c2017-01-01 20:25:03 -080043static int test_repeated_init_and_subinterpreters(void)
Antoine Pitrou8e605772011-04-25 21:21:07 +020044{
45 PyThreadState *mainstate, *substate;
46 PyGILState_STATE gilstate;
47 int i, j;
48
Ned Deily939231b2016-08-16 00:17:42 -040049 for (i=0; i<15; i++) {
Antoine Pitrou8e605772011-04-25 21:21:07 +020050 printf("--- Pass %d ---\n", i);
Nick Coghlan7d270ee2013-10-17 22:35:35 +100051 _testembed_Py_Initialize();
Antoine Pitrou8e605772011-04-25 21:21:07 +020052 mainstate = PyThreadState_Get();
53
54 PyEval_InitThreads();
55 PyEval_ReleaseThread(mainstate);
56
57 gilstate = PyGILState_Ensure();
58 print_subinterp();
59 PyThreadState_Swap(NULL);
60
61 for (j=0; j<3; j++) {
62 substate = Py_NewInterpreter();
63 print_subinterp();
64 Py_EndInterpreter(substate);
65 }
66
67 PyThreadState_Swap(mainstate);
68 print_subinterp();
69 PyGILState_Release(gilstate);
Antoine Pitrou8e605772011-04-25 21:21:07 +020070
71 PyEval_RestoreThread(mainstate);
72 Py_Finalize();
73 }
Steve Dowerea74f0c2017-01-01 20:25:03 -080074 return 0;
Nick Coghlan7d270ee2013-10-17 22:35:35 +100075}
76
77/*****************************************************
78 * Test forcing a particular IO encoding
79 *****************************************************/
80
81static void check_stdio_details(const char *encoding, const char * errors)
82{
83 /* Output info for the test case to check */
84 if (encoding) {
85 printf("Expected encoding: %s\n", encoding);
86 } else {
87 printf("Expected encoding: default\n");
88 }
89 if (errors) {
90 printf("Expected errors: %s\n", errors);
91 } else {
92 printf("Expected errors: default\n");
93 }
94 fflush(stdout);
95 /* Force the given IO encoding */
96 Py_SetStandardStreamEncoding(encoding, errors);
97 _testembed_Py_Initialize();
98 PyRun_SimpleString(
99 "import sys;"
100 "print('stdin: {0.encoding}:{0.errors}'.format(sys.stdin));"
101 "print('stdout: {0.encoding}:{0.errors}'.format(sys.stdout));"
102 "print('stderr: {0.encoding}:{0.errors}'.format(sys.stderr));"
103 "sys.stdout.flush()"
104 );
105 Py_Finalize();
106}
107
Steve Dowerea74f0c2017-01-01 20:25:03 -0800108static int test_forced_io_encoding(void)
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000109{
110 /* Check various combinations */
111 printf("--- Use defaults ---\n");
112 check_stdio_details(NULL, NULL);
113 printf("--- Set errors only ---\n");
Victor Stinnerb2bef622014-03-18 02:38:12 +0100114 check_stdio_details(NULL, "ignore");
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000115 printf("--- Set encoding only ---\n");
Victor Stinner9e4994d2018-08-28 23:26:33 +0200116 check_stdio_details("iso8859-1", NULL);
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000117 printf("--- Set encoding and errors ---\n");
Victor Stinner9e4994d2018-08-28 23:26:33 +0200118 check_stdio_details("iso8859-1", "replace");
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000119
120 /* Check calling after initialization fails */
121 Py_Initialize();
122
123 if (Py_SetStandardStreamEncoding(NULL, NULL) == 0) {
124 printf("Unexpected success calling Py_SetStandardStreamEncoding");
125 }
126 Py_Finalize();
Steve Dowerea74f0c2017-01-01 20:25:03 -0800127 return 0;
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000128}
129
Victor Stinner9e87e772017-11-24 12:09:24 +0100130/*********************************************************
131 * Test parts of the C-API that work before initialization
132 *********************************************************/
133
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000134/* The pre-initialization tests tend to break by segfaulting, so explicitly
135 * flushed progress messages make the broken API easier to find when they fail.
136 */
137#define _Py_EMBED_PREINIT_CHECK(msg) \
138 do {printf(msg); fflush(stdout);} while (0);
139
Victor Stinner9e87e772017-11-24 12:09:24 +0100140static int test_pre_initialization_api(void)
141{
Victor Stinnera9df6512019-03-05 23:31:54 +0100142 /* the test doesn't support custom memory allocators */
143 putenv("PYTHONMALLOC=");
144
Nick Coghlan42746092017-11-26 14:19:13 +1000145 /* Leading "./" ensures getpath.c can still find the standard library */
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000146 _Py_EMBED_PREINIT_CHECK("Checking Py_DecodeLocale\n");
Nick Coghlan42746092017-11-26 14:19:13 +1000147 wchar_t *program = Py_DecodeLocale("./spam", NULL);
Victor Stinner9e87e772017-11-24 12:09:24 +0100148 if (program == NULL) {
149 fprintf(stderr, "Fatal error: cannot decode program name\n");
150 return 1;
151 }
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000152 _Py_EMBED_PREINIT_CHECK("Checking Py_SetProgramName\n");
Victor Stinner9e87e772017-11-24 12:09:24 +0100153 Py_SetProgramName(program);
154
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000155 _Py_EMBED_PREINIT_CHECK("Initializing interpreter\n");
Victor Stinner9e87e772017-11-24 12:09:24 +0100156 Py_Initialize();
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000157 _Py_EMBED_PREINIT_CHECK("Check sys module contents\n");
158 PyRun_SimpleString("import sys; "
159 "print('sys.executable:', sys.executable)");
160 _Py_EMBED_PREINIT_CHECK("Finalizing interpreter\n");
Victor Stinner9e87e772017-11-24 12:09:24 +0100161 Py_Finalize();
162
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000163 _Py_EMBED_PREINIT_CHECK("Freeing memory allocated by Py_DecodeLocale\n");
Victor Stinner9e87e772017-11-24 12:09:24 +0100164 PyMem_RawFree(program);
165 return 0;
166}
167
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000168
169/* bpo-33042: Ensure embedding apps can predefine sys module options */
170static int test_pre_initialization_sys_options(void)
171{
Nick Coghlan69f5c732018-03-30 15:36:42 +1000172 /* We allocate a couple of the options dynamically, and then delete
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000173 * them before calling Py_Initialize. This ensures the interpreter isn't
174 * relying on the caller to keep the passed in strings alive.
175 */
Nick Coghlan69f5c732018-03-30 15:36:42 +1000176 const wchar_t *static_warnoption = L"once";
177 const wchar_t *static_xoption = L"also_not_an_option=2";
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000178 size_t warnoption_len = wcslen(static_warnoption);
179 size_t xoption_len = wcslen(static_xoption);
Nick Coghlan69f5c732018-03-30 15:36:42 +1000180 wchar_t *dynamic_once_warnoption = \
181 (wchar_t *) calloc(warnoption_len+1, sizeof(wchar_t));
182 wchar_t *dynamic_xoption = \
183 (wchar_t *) calloc(xoption_len+1, sizeof(wchar_t));
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000184 wcsncpy(dynamic_once_warnoption, static_warnoption, warnoption_len+1);
185 wcsncpy(dynamic_xoption, static_xoption, xoption_len+1);
186
187 _Py_EMBED_PREINIT_CHECK("Checking PySys_AddWarnOption\n");
188 PySys_AddWarnOption(L"default");
189 _Py_EMBED_PREINIT_CHECK("Checking PySys_ResetWarnOptions\n");
190 PySys_ResetWarnOptions();
191 _Py_EMBED_PREINIT_CHECK("Checking PySys_AddWarnOption linked list\n");
192 PySys_AddWarnOption(dynamic_once_warnoption);
193 PySys_AddWarnOption(L"module");
194 PySys_AddWarnOption(L"default");
195 _Py_EMBED_PREINIT_CHECK("Checking PySys_AddXOption\n");
196 PySys_AddXOption(L"not_an_option=1");
197 PySys_AddXOption(dynamic_xoption);
198
199 /* Delete the dynamic options early */
200 free(dynamic_once_warnoption);
201 dynamic_once_warnoption = NULL;
202 free(dynamic_xoption);
203 dynamic_xoption = NULL;
204
205 _Py_EMBED_PREINIT_CHECK("Initializing interpreter\n");
206 _testembed_Py_Initialize();
207 _Py_EMBED_PREINIT_CHECK("Check sys module contents\n");
208 PyRun_SimpleString("import sys; "
209 "print('sys.warnoptions:', sys.warnoptions); "
210 "print('sys._xoptions:', sys._xoptions); "
211 "warnings = sys.modules['warnings']; "
212 "latest_filters = [f[0] for f in warnings.filters[:3]]; "
213 "print('warnings.filters[:3]:', latest_filters)");
214 _Py_EMBED_PREINIT_CHECK("Finalizing interpreter\n");
215 Py_Finalize();
216
217 return 0;
218}
219
220
221/* bpo-20891: Avoid race condition when initialising the GIL */
Victor Stinnerb4d1e1f2017-11-30 22:05:00 +0100222static void bpo20891_thread(void *lockp)
223{
224 PyThread_type_lock lock = *((PyThread_type_lock*)lockp);
225
226 PyGILState_STATE state = PyGILState_Ensure();
227 if (!PyGILState_Check()) {
228 fprintf(stderr, "PyGILState_Check failed!");
229 abort();
230 }
231
232 PyGILState_Release(state);
233
234 PyThread_release_lock(lock);
235
236 PyThread_exit_thread();
237}
238
239static int test_bpo20891(void)
240{
Victor Stinnera9df6512019-03-05 23:31:54 +0100241 /* the test doesn't support custom memory allocators */
242 putenv("PYTHONMALLOC=");
243
Victor Stinnerb4d1e1f2017-11-30 22:05:00 +0100244 /* bpo-20891: Calling PyGILState_Ensure in a non-Python thread before
245 calling PyEval_InitThreads() must not crash. PyGILState_Ensure() must
246 call PyEval_InitThreads() for us in this case. */
247 PyThread_type_lock lock = PyThread_allocate_lock();
248 if (!lock) {
249 fprintf(stderr, "PyThread_allocate_lock failed!");
250 return 1;
251 }
252
253 _testembed_Py_Initialize();
254
255 unsigned long thrd = PyThread_start_new_thread(bpo20891_thread, &lock);
256 if (thrd == PYTHREAD_INVALID_THREAD_ID) {
257 fprintf(stderr, "PyThread_start_new_thread failed!");
258 return 1;
259 }
260 PyThread_acquire_lock(lock, WAIT_LOCK);
261
262 Py_BEGIN_ALLOW_THREADS
263 /* wait until the thread exit */
264 PyThread_acquire_lock(lock, WAIT_LOCK);
265 Py_END_ALLOW_THREADS
266
267 PyThread_free_lock(lock);
268
269 return 0;
270}
271
Victor Stinner209abf72018-06-22 19:14:51 +0200272static int test_initialize_twice(void)
273{
274 _testembed_Py_Initialize();
275
276 /* bpo-33932: Calling Py_Initialize() twice should do nothing
277 * (and not crash!). */
278 Py_Initialize();
279
280 Py_Finalize();
281
282 return 0;
283}
284
Victor Stinnerfb47bca2018-07-20 17:34:23 +0200285static int test_initialize_pymain(void)
286{
287 wchar_t *argv[] = {L"PYTHON", L"-c",
288 L"import sys; print(f'Py_Main() after Py_Initialize: sys.argv={sys.argv}')",
289 L"arg2"};
290 _testembed_Py_Initialize();
291
292 /* bpo-34008: Calling Py_Main() after Py_Initialize() must not crash */
293 Py_Main(Py_ARRAY_LENGTH(argv), argv);
294
295 Py_Finalize();
296
297 return 0;
298}
299
Victor Stinner9e87e772017-11-24 12:09:24 +0100300
Victor Stinner00b137c2018-11-13 19:59:26 +0100301static void
302dump_config(void)
303{
Victor Stinner23bace22019-04-18 11:37:26 +0200304 (void) PyRun_SimpleStringFlags(
305 "import _testinternalcapi, json; "
306 "print(json.dumps(_testinternalcapi.get_configs()))",
307 0);
Victor Stinner00b137c2018-11-13 19:59:26 +0100308}
309
310
Victor Stinner56b29b62018-07-26 18:57:56 +0200311static int test_init_default_config(void)
312{
313 _testembed_Py_Initialize();
314 dump_config();
315 Py_Finalize();
316 return 0;
317}
318
319
320static int test_init_global_config(void)
321{
322 /* FIXME: test Py_IgnoreEnvironmentFlag */
323
324 putenv("PYTHONUTF8=0");
325 Py_UTF8Mode = 1;
326
327 /* Test initialization from global configuration variables (Py_xxx) */
328 Py_SetProgramName(L"./globalvar");
329
330 /* Py_IsolatedFlag is not tested */
331 Py_NoSiteFlag = 1;
332 Py_BytesWarningFlag = 1;
333
334 putenv("PYTHONINSPECT=");
335 Py_InspectFlag = 1;
336
337 putenv("PYTHONOPTIMIZE=0");
338 Py_InteractiveFlag = 1;
339
340 putenv("PYTHONDEBUG=0");
341 Py_OptimizeFlag = 2;
342
343 /* Py_DebugFlag is not tested */
344
345 putenv("PYTHONDONTWRITEBYTECODE=");
346 Py_DontWriteBytecodeFlag = 1;
347
348 putenv("PYTHONVERBOSE=0");
349 Py_VerboseFlag = 1;
350
351 Py_QuietFlag = 1;
352 Py_NoUserSiteDirectory = 1;
353
354 putenv("PYTHONUNBUFFERED=");
355 Py_UnbufferedStdioFlag = 1;
356
Victor Stinnerb75d7e22018-08-01 02:13:04 +0200357 Py_FrozenFlag = 1;
358
Victor Stinner56b29b62018-07-26 18:57:56 +0200359 /* FIXME: test Py_LegacyWindowsFSEncodingFlag */
360 /* FIXME: test Py_LegacyWindowsStdioFlag */
361
Victor Stinner56b29b62018-07-26 18:57:56 +0200362 Py_Initialize();
363 dump_config();
364 Py_Finalize();
365 return 0;
366}
367
368
369static int test_init_from_config(void)
370{
Victor Stinner20004952019-03-26 02:31:11 +0100371 _PyInitError err;
372
373 _PyPreConfig preconfig = _PyPreConfig_INIT;
374
375 putenv("PYTHONMALLOC=malloc_debug");
376 preconfig.allocator = "malloc";
377
378 putenv("PYTHONUTF8=0");
379 Py_UTF8Mode = 0;
380 preconfig.utf8_mode = 1;
381
Victor Stinner5ac27a52019-03-27 13:40:14 +0100382 err = _Py_PreInitialize(&preconfig);
Victor Stinner20004952019-03-26 02:31:11 +0100383 if (_Py_INIT_FAILED(err)) {
384 _Py_ExitInitError(err);
385 }
386
Victor Stinner56b29b62018-07-26 18:57:56 +0200387 /* Test _Py_InitializeFromConfig() */
388 _PyCoreConfig config = _PyCoreConfig_INIT;
389 config.install_signal_handlers = 0;
390
391 /* FIXME: test use_environment */
392
393 putenv("PYTHONHASHSEED=42");
394 config.use_hash_seed = 1;
395 config.hash_seed = 123;
396
Victor Stinner56b29b62018-07-26 18:57:56 +0200397 /* dev_mode=1 is tested in test_init_dev_mode() */
398
399 putenv("PYTHONFAULTHANDLER=");
400 config.faulthandler = 1;
401
402 putenv("PYTHONTRACEMALLOC=0");
403 config.tracemalloc = 2;
404
405 putenv("PYTHONPROFILEIMPORTTIME=0");
406 config.import_time = 1;
407
408 config.show_ref_count = 1;
409 config.show_alloc_count = 1;
410 /* FIXME: test dump_refs: bpo-34223 */
411
412 putenv("PYTHONMALLOCSTATS=0");
413 config.malloc_stats = 1;
414
Victor Stinner56b29b62018-07-26 18:57:56 +0200415 putenv("PYTHONPYCACHEPREFIX=env_pycache_prefix");
416 config.pycache_prefix = L"conf_pycache_prefix";
417
418 Py_SetProgramName(L"./globalvar");
419 config.program_name = L"./conf_program_name";
420
Victor Stinner2f549082019-03-29 15:13:46 +0100421 static wchar_t* argv[] = {
422 L"python3",
Victor Stinner01de89c2018-11-14 17:39:45 +0100423 L"-c",
424 L"pass",
Victor Stinner2f549082019-03-29 15:13:46 +0100425 L"arg2",
Victor Stinner01de89c2018-11-14 17:39:45 +0100426 };
Victor Stinner74f65682019-03-15 15:08:05 +0100427 config.argv.length = Py_ARRAY_LENGTH(argv);
428 config.argv.items = argv;
Victor Stinner01de89c2018-11-14 17:39:45 +0100429
Victor Stinner56b29b62018-07-26 18:57:56 +0200430 config.program = L"conf_program";
Victor Stinner01de89c2018-11-14 17:39:45 +0100431
432 static wchar_t* xoptions[3] = {
433 L"core_xoption1=3",
434 L"core_xoption2=",
435 L"core_xoption3",
436 };
Victor Stinner74f65682019-03-15 15:08:05 +0100437 config.xoptions.length = Py_ARRAY_LENGTH(xoptions);
438 config.xoptions.items = xoptions;
Victor Stinner01de89c2018-11-14 17:39:45 +0100439
Victor Stinnerf8ba6f52019-03-26 16:58:50 +0100440 static wchar_t* warnoptions[1] = {
Victor Stinner01de89c2018-11-14 17:39:45 +0100441 L"error::ResourceWarning",
442 };
Victor Stinner74f65682019-03-15 15:08:05 +0100443 config.warnoptions.length = Py_ARRAY_LENGTH(warnoptions);
444 config.warnoptions.items = warnoptions;
Victor Stinner01de89c2018-11-14 17:39:45 +0100445
Victor Stinner56b29b62018-07-26 18:57:56 +0200446 /* FIXME: test module_search_path_env */
447 /* FIXME: test home */
448 /* FIXME: test path config: module_search_path .. dll_path */
449
450 putenv("PYTHONVERBOSE=0");
451 Py_VerboseFlag = 0;
452 config.verbose = 1;
453
454 Py_NoSiteFlag = 0;
455 config.site_import = 0;
456
457 Py_BytesWarningFlag = 0;
458 config.bytes_warning = 1;
459
460 putenv("PYTHONINSPECT=");
461 Py_InspectFlag = 0;
462 config.inspect = 1;
463
464 Py_InteractiveFlag = 0;
465 config.interactive = 1;
466
467 putenv("PYTHONOPTIMIZE=0");
468 Py_OptimizeFlag = 1;
469 config.optimization_level = 2;
470
Victor Stinner98512272018-08-01 03:07:00 +0200471 /* FIXME: test parser_debug */
Victor Stinner56b29b62018-07-26 18:57:56 +0200472
473 putenv("PYTHONDONTWRITEBYTECODE=");
474 Py_DontWriteBytecodeFlag = 0;
475 config.write_bytecode = 0;
476
477 Py_QuietFlag = 0;
478 config.quiet = 1;
479
480 putenv("PYTHONUNBUFFERED=");
481 Py_UnbufferedStdioFlag = 0;
Victor Stinner98512272018-08-01 03:07:00 +0200482 config.buffered_stdio = 0;
Victor Stinner56b29b62018-07-26 18:57:56 +0200483
Victor Stinnerdfe0dc72018-08-29 11:47:29 +0200484 putenv("PYTHONIOENCODING=cp424");
485 Py_SetStandardStreamEncoding("ascii", "ignore");
Victor Stinner01de89c2018-11-14 17:39:45 +0100486#ifdef MS_WINDOWS
487 /* Py_SetStandardStreamEncoding() sets Py_LegacyWindowsStdioFlag to 1.
488 Force it to 0 through the config. */
489 config.legacy_windows_stdio = 0;
490#endif
Victor Stinnerdfe0dc72018-08-29 11:47:29 +0200491 config.stdio_encoding = "iso8859-1";
492 config.stdio_errors = "replace";
493
Victor Stinner56b29b62018-07-26 18:57:56 +0200494 putenv("PYTHONNOUSERSITE=");
495 Py_NoUserSiteDirectory = 0;
496 config.user_site_directory = 0;
497
Victor Stinnercb9fbd32019-05-01 23:51:56 -0400498 config.check_hash_pycs_mode = L"always";
Victor Stinner56b29b62018-07-26 18:57:56 +0200499
Victor Stinnerb75d7e22018-08-01 02:13:04 +0200500 Py_FrozenFlag = 0;
501 config._frozen = 1;
502
Victor Stinner5ac27a52019-03-27 13:40:14 +0100503 err = _Py_InitializeFromConfig(&config);
Victor Stinner56b29b62018-07-26 18:57:56 +0200504 if (_Py_INIT_FAILED(err)) {
Victor Stinnerdfe88472019-03-01 12:14:41 +0100505 _Py_ExitInitError(err);
Victor Stinner56b29b62018-07-26 18:57:56 +0200506 }
507 dump_config();
508 Py_Finalize();
509 return 0;
510}
511
512
513static void test_init_env_putenvs(void)
514{
515 putenv("PYTHONHASHSEED=42");
Victor Stinner25d13f32019-03-06 12:51:53 +0100516 putenv("PYTHONMALLOC=malloc");
Victor Stinner56b29b62018-07-26 18:57:56 +0200517 putenv("PYTHONTRACEMALLOC=2");
518 putenv("PYTHONPROFILEIMPORTTIME=1");
519 putenv("PYTHONMALLOCSTATS=1");
520 putenv("PYTHONUTF8=1");
521 putenv("PYTHONVERBOSE=1");
522 putenv("PYTHONINSPECT=1");
523 putenv("PYTHONOPTIMIZE=2");
524 putenv("PYTHONDONTWRITEBYTECODE=1");
525 putenv("PYTHONUNBUFFERED=1");
526 putenv("PYTHONPYCACHEPREFIX=env_pycache_prefix");
527 putenv("PYTHONNOUSERSITE=1");
528 putenv("PYTHONFAULTHANDLER=1");
Victor Stinnerdfe0dc72018-08-29 11:47:29 +0200529 putenv("PYTHONIOENCODING=iso8859-1:replace");
Victor Stinner56b29b62018-07-26 18:57:56 +0200530 /* FIXME: test PYTHONWARNINGS */
531 /* FIXME: test PYTHONEXECUTABLE */
532 /* FIXME: test PYTHONHOME */
533 /* FIXME: test PYTHONDEBUG */
534 /* FIXME: test PYTHONDUMPREFS */
535 /* FIXME: test PYTHONCOERCECLOCALE */
536 /* FIXME: test PYTHONPATH */
537}
538
539
540static int test_init_env(void)
541{
542 /* Test initialization from environment variables */
543 Py_IgnoreEnvironmentFlag = 0;
544 test_init_env_putenvs();
545 _testembed_Py_Initialize();
546 dump_config();
547 Py_Finalize();
548 return 0;
549}
550
551
Victor Stinner25d13f32019-03-06 12:51:53 +0100552static void test_init_env_dev_mode_putenvs(void)
553{
554 test_init_env_putenvs();
555 putenv("PYTHONMALLOC=");
556 putenv("PYTHONFAULTHANDLER=");
557 putenv("PYTHONDEVMODE=1");
558}
559
560
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100561static int test_init_env_dev_mode(void)
562{
563 /* Test initialization from environment variables */
564 Py_IgnoreEnvironmentFlag = 0;
565 test_init_env_dev_mode_putenvs();
566 _testembed_Py_Initialize();
567 dump_config();
568 Py_Finalize();
569 return 0;
570}
571
572
Victor Stinner25d13f32019-03-06 12:51:53 +0100573static int test_init_env_dev_mode_alloc(void)
574{
575 /* Test initialization from environment variables */
576 Py_IgnoreEnvironmentFlag = 0;
577 test_init_env_dev_mode_putenvs();
578 putenv("PYTHONMALLOC=malloc");
579 _testembed_Py_Initialize();
580 dump_config();
581 Py_Finalize();
582 return 0;
583}
584
585
Victor Stinner56b29b62018-07-26 18:57:56 +0200586static int test_init_isolated(void)
587{
Victor Stinner20004952019-03-26 02:31:11 +0100588 _PyInitError err;
589
Victor Stinner56b29b62018-07-26 18:57:56 +0200590 /* Test _PyCoreConfig.isolated=1 */
591 _PyCoreConfig config = _PyCoreConfig_INIT;
592
Victor Stinnercad1f742019-03-05 02:01:27 +0100593 Py_IsolatedFlag = 0;
Victor Stinner20004952019-03-26 02:31:11 +0100594 config.isolated = 1;
Victor Stinnercad1f742019-03-05 02:01:27 +0100595
Victor Stinner56b29b62018-07-26 18:57:56 +0200596 /* Use path starting with "./" avoids a search along the PATH */
597 config.program_name = L"./_testembed";
598
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100599 test_init_env_dev_mode_putenvs();
Victor Stinner5ac27a52019-03-27 13:40:14 +0100600 err = _Py_InitializeFromConfig(&config);
Victor Stinner56b29b62018-07-26 18:57:56 +0200601 if (_Py_INIT_FAILED(err)) {
Victor Stinnerdfe88472019-03-01 12:14:41 +0100602 _Py_ExitInitError(err);
Victor Stinner56b29b62018-07-26 18:57:56 +0200603 }
604 dump_config();
605 Py_Finalize();
606 return 0;
607}
608
609
Victor Stinner6da20a42019-03-27 00:26:18 +0100610/* _PyPreConfig.isolated=1, _PyCoreConfig.isolated=0 */
611static int test_preinit_isolated1(void)
612{
613 _PyInitError err;
614
615 _PyPreConfig preconfig = _PyPreConfig_INIT;
Victor Stinner6da20a42019-03-27 00:26:18 +0100616 preconfig.isolated = 1;
617
Victor Stinner5ac27a52019-03-27 13:40:14 +0100618 err = _Py_PreInitialize(&preconfig);
Victor Stinner6da20a42019-03-27 00:26:18 +0100619 if (_Py_INIT_FAILED(err)) {
620 _Py_ExitInitError(err);
621 }
622
623 _PyCoreConfig config = _PyCoreConfig_INIT;
624 config.program_name = L"./_testembed";
625
626 test_init_env_dev_mode_putenvs();
Victor Stinner5ac27a52019-03-27 13:40:14 +0100627 err = _Py_InitializeFromConfig(&config);
Victor Stinner6da20a42019-03-27 00:26:18 +0100628 if (_Py_INIT_FAILED(err)) {
629 _Py_ExitInitError(err);
630 }
631 dump_config();
632 Py_Finalize();
633 return 0;
634}
635
636
637/* _PyPreConfig.isolated=0, _PyCoreConfig.isolated=1 */
638static int test_preinit_isolated2(void)
639{
640 _PyInitError err;
641
642 _PyPreConfig preconfig = _PyPreConfig_INIT;
Victor Stinner6da20a42019-03-27 00:26:18 +0100643 preconfig.isolated = 0;
644
Victor Stinner5ac27a52019-03-27 13:40:14 +0100645 err = _Py_PreInitialize(&preconfig);
Victor Stinner6da20a42019-03-27 00:26:18 +0100646 if (_Py_INIT_FAILED(err)) {
647 _Py_ExitInitError(err);
648 }
649
650 /* Test _PyCoreConfig.isolated=1 */
651 _PyCoreConfig config = _PyCoreConfig_INIT;
652
653 Py_IsolatedFlag = 0;
654 config.isolated = 1;
655
656 /* Use path starting with "./" avoids a search along the PATH */
657 config.program_name = L"./_testembed";
658
659 test_init_env_dev_mode_putenvs();
Victor Stinner5ac27a52019-03-27 13:40:14 +0100660 err = _Py_InitializeFromConfig(&config);
Victor Stinner6da20a42019-03-27 00:26:18 +0100661 if (_Py_INIT_FAILED(err)) {
662 _Py_ExitInitError(err);
663 }
664 dump_config();
665 Py_Finalize();
666 return 0;
667}
668
669
Victor Stinner56b29b62018-07-26 18:57:56 +0200670static int test_init_dev_mode(void)
671{
672 _PyCoreConfig config = _PyCoreConfig_INIT;
673 putenv("PYTHONFAULTHANDLER=");
674 putenv("PYTHONMALLOC=");
Victor Stinner20004952019-03-26 02:31:11 +0100675 config.dev_mode = 1;
Victor Stinner56b29b62018-07-26 18:57:56 +0200676 config.program_name = L"./_testembed";
Victor Stinner5ac27a52019-03-27 13:40:14 +0100677 _PyInitError err = _Py_InitializeFromConfig(&config);
Victor Stinner56b29b62018-07-26 18:57:56 +0200678 if (_Py_INIT_FAILED(err)) {
Victor Stinnerdfe88472019-03-01 12:14:41 +0100679 _Py_ExitInitError(err);
Victor Stinner56b29b62018-07-26 18:57:56 +0200680 }
681 dump_config();
682 Py_Finalize();
683 return 0;
684}
685
686
Victor Stinner2f549082019-03-29 15:13:46 +0100687static int test_run_main(void)
688{
689 _PyCoreConfig config = _PyCoreConfig_INIT;
690
691 wchar_t *argv[] = {L"python3", L"-c",
692 (L"import sys; "
693 L"print(f'_Py_RunMain(): sys.argv={sys.argv}')"),
694 L"arg2"};
695 config.argv.length = Py_ARRAY_LENGTH(argv);
696 config.argv.items = argv;
697 config.program_name = L"./python3";
698
699 _PyInitError err = _Py_InitializeFromConfig(&config);
700 if (_Py_INIT_FAILED(err)) {
701 _Py_ExitInitError(err);
702 }
703
704 return _Py_RunMain();
705}
706
707
Steve Dowerea74f0c2017-01-01 20:25:03 -0800708/* *********************************************************
709 * List of test cases and the function that implements it.
Serhiy Storchaka13ad3b72017-09-14 09:38:36 +0300710 *
Steve Dowerea74f0c2017-01-01 20:25:03 -0800711 * Names are compared case-sensitively with the first
712 * argument. If no match is found, or no first argument was
713 * provided, the names of all test cases are printed and
714 * the exit code will be -1.
715 *
716 * The int returned from test functions is used as the exit
717 * code, and test_capi treats all non-zero exit codes as a
Serhiy Storchaka13ad3b72017-09-14 09:38:36 +0300718 * failed test.
Steve Dowerea74f0c2017-01-01 20:25:03 -0800719 *********************************************************/
720struct TestCase
721{
722 const char *name;
723 int (*func)(void);
724};
725
726static struct TestCase TestCases[] = {
727 { "forced_io_encoding", test_forced_io_encoding },
728 { "repeated_init_and_subinterpreters", test_repeated_init_and_subinterpreters },
Victor Stinner9e87e772017-11-24 12:09:24 +0100729 { "pre_initialization_api", test_pre_initialization_api },
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000730 { "pre_initialization_sys_options", test_pre_initialization_sys_options },
Victor Stinnerb4d1e1f2017-11-30 22:05:00 +0100731 { "bpo20891", test_bpo20891 },
Victor Stinner209abf72018-06-22 19:14:51 +0200732 { "initialize_twice", test_initialize_twice },
Victor Stinnerfb47bca2018-07-20 17:34:23 +0200733 { "initialize_pymain", test_initialize_pymain },
Victor Stinner56b29b62018-07-26 18:57:56 +0200734 { "init_default_config", test_init_default_config },
735 { "init_global_config", test_init_global_config },
736 { "init_from_config", test_init_from_config },
737 { "init_env", test_init_env },
Victor Stinnerb35be4b2019-03-05 17:37:44 +0100738 { "init_env_dev_mode", test_init_env_dev_mode },
Victor Stinner25d13f32019-03-06 12:51:53 +0100739 { "init_env_dev_mode_alloc", test_init_env_dev_mode_alloc },
Victor Stinner56b29b62018-07-26 18:57:56 +0200740 { "init_dev_mode", test_init_dev_mode },
741 { "init_isolated", test_init_isolated },
Victor Stinner6da20a42019-03-27 00:26:18 +0100742 { "preinit_isolated1", test_preinit_isolated1 },
743 { "preinit_isolated2", test_preinit_isolated2 },
Victor Stinner2f549082019-03-29 15:13:46 +0100744 { "run_main", test_run_main },
Steve Dowerea74f0c2017-01-01 20:25:03 -0800745 { NULL, NULL }
746};
747
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000748int main(int argc, char *argv[])
749{
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000750 if (argc > 1) {
Steve Dowerea74f0c2017-01-01 20:25:03 -0800751 for (struct TestCase *tc = TestCases; tc && tc->name; tc++) {
752 if (strcmp(argv[1], tc->name) == 0)
753 return (*tc->func)();
754 }
Nick Coghlan7d270ee2013-10-17 22:35:35 +1000755 }
Steve Dowerea74f0c2017-01-01 20:25:03 -0800756
757 /* No match found, or no test name provided, so display usage */
758 printf("Python " PY_VERSION " _testembed executable for embedded interpreter tests\n"
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000759 "Normally executed via 'EmbeddingTests' in Lib/test/test_embed.py\n\n"
Steve Dowerea74f0c2017-01-01 20:25:03 -0800760 "Usage: %s TESTNAME\n\nAll available tests:\n", argv[0]);
761 for (struct TestCase *tc = TestCases; tc && tc->name; tc++) {
762 printf(" %s\n", tc->name);
763 }
764
Nick Coghlanbc77eff2018-03-25 20:44:30 +1000765 /* Non-zero exit code will cause test_embed.py tests to fail.
Steve Dowerea74f0c2017-01-01 20:25:03 -0800766 This is intentional. */
767 return -1;
Antoine Pitrou8e605772011-04-25 21:21:07 +0200768}