1 #ifndef Py_BUILD_CORE_MODULE
2 # define Py_BUILD_CORE_MODULE
3 #endif
4 #define NEEDS_PY_IDENTIFIER
5
6 /* Always enable assertion (even in release mode) */
7 #undef NDEBUG
8
9 #include <Python.h>
10 #include "pycore_initconfig.h" // _PyConfig_InitCompatConfig()
11 #include "pycore_runtime.h" // _PyRuntime
12 #include "pycore_import.h" // _PyImport_FrozenBootstrap
13 #include <Python.h>
14 #include <inttypes.h>
15 #include <stdio.h>
16 #include <stdlib.h> // putenv()
17 #include <wchar.h>
18
19 int main_argc;
20 char **main_argv;
21
22 /*********************************************************
23 * Embedded interpreter tests that need a custom exe
24 *
25 * Executed via Lib/test/test_embed.py
26 *********************************************************/
27
28 // Use to display the usage
29 #define PROGRAM "test_embed"
30
31 /* Use path starting with "./" avoids a search along the PATH */
32 #define PROGRAM_NAME L"./_testembed"
33
34 #define INIT_LOOPS 4
35
36 // Ignore Py_DEPRECATED() compiler warnings: deprecated functions are
37 // tested on purpose here.
38 _Py_COMP_DIAG_PUSH
39 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
40
41
error(const char * msg)42 static void error(const char *msg)
43 {
44 fprintf(stderr, "ERROR: %s\n", msg);
45 fflush(stderr);
46 }
47
48
config_set_string(PyConfig * config,wchar_t ** config_str,const wchar_t * str)49 static void config_set_string(PyConfig *config, wchar_t **config_str, const wchar_t *str)
50 {
51 PyStatus status = PyConfig_SetString(config, config_str, str);
52 if (PyStatus_Exception(status)) {
53 PyConfig_Clear(config);
54 Py_ExitStatusException(status);
55 }
56 }
57
58
config_set_program_name(PyConfig * config)59 static void config_set_program_name(PyConfig *config)
60 {
61 const wchar_t *program_name = PROGRAM_NAME;
62 config_set_string(config, &config->program_name, program_name);
63 }
64
65
init_from_config_clear(PyConfig * config)66 static void init_from_config_clear(PyConfig *config)
67 {
68 PyStatus status = Py_InitializeFromConfig(config);
69 PyConfig_Clear(config);
70 if (PyStatus_Exception(status)) {
71 Py_ExitStatusException(status);
72 }
73 }
74
75
_testembed_Py_InitializeFromConfig(void)76 static void _testembed_Py_InitializeFromConfig(void)
77 {
78 PyConfig config;
79 _PyConfig_InitCompatConfig(&config);
80 config_set_program_name(&config);
81 init_from_config_clear(&config);
82 }
83
_testembed_Py_Initialize(void)84 static void _testembed_Py_Initialize(void)
85 {
86 Py_SetProgramName(PROGRAM_NAME);
87 Py_Initialize();
88 }
89
90
91 /*****************************************************
92 * Test repeated initialisation and subinterpreters
93 *****************************************************/
94
print_subinterp(void)95 static void print_subinterp(void)
96 {
97 /* Output information about the interpreter in the format
98 expected in Lib/test/test_capi.py (test_subinterps). */
99 PyThreadState *ts = PyThreadState_Get();
100 PyInterpreterState *interp = ts->interp;
101 int64_t id = PyInterpreterState_GetID(interp);
102 printf("interp %" PRId64 " <0x%" PRIXPTR ">, thread state <0x%" PRIXPTR ">: ",
103 id, (uintptr_t)interp, (uintptr_t)ts);
104 fflush(stdout);
105 PyRun_SimpleString(
106 "import sys;"
107 "print('id(modules) =', id(sys.modules));"
108 "sys.stdout.flush()"
109 );
110 }
111
test_repeated_init_and_subinterpreters(void)112 static int test_repeated_init_and_subinterpreters(void)
113 {
114 PyThreadState *mainstate, *substate;
115 PyGILState_STATE gilstate;
116
117 for (int i=1; i <= INIT_LOOPS; i++) {
118 printf("--- Pass %d ---\n", i);
119 _testembed_Py_InitializeFromConfig();
120 mainstate = PyThreadState_Get();
121
122 PyEval_ReleaseThread(mainstate);
123
124 gilstate = PyGILState_Ensure();
125 print_subinterp();
126 PyThreadState_Swap(NULL);
127
128 for (int j=0; j<3; j++) {
129 substate = Py_NewInterpreter();
130 print_subinterp();
131 Py_EndInterpreter(substate);
132 }
133
134 PyThreadState_Swap(mainstate);
135 print_subinterp();
136 PyGILState_Release(gilstate);
137
138 PyEval_RestoreThread(mainstate);
139 Py_Finalize();
140 }
141 return 0;
142 }
143
144 #define EMBEDDED_EXT_NAME "embedded_ext"
145
146 static PyModuleDef embedded_ext = {
147 PyModuleDef_HEAD_INIT,
148 .m_name = EMBEDDED_EXT_NAME,
149 .m_size = 0,
150 };
151
152 static PyObject*
PyInit_embedded_ext(void)153 PyInit_embedded_ext(void)
154 {
155 return PyModule_Create(&embedded_ext);
156 }
157
158 /****************************************************************************
159 * Call Py_Initialize()/Py_Finalize() multiple times and execute Python code
160 ***************************************************************************/
161
162 // Used by bpo-46417 to test that structseq types used by the sys module are
163 // cleared properly and initialized again properly when Python is finalized
164 // multiple times.
test_repeated_init_exec(void)165 static int test_repeated_init_exec(void)
166 {
167 if (main_argc < 3) {
168 fprintf(stderr, "usage: %s test_repeated_init_exec CODE\n", PROGRAM);
169 exit(1);
170 }
171 const char *code = main_argv[2];
172
173 for (int i=1; i <= INIT_LOOPS; i++) {
174 fprintf(stderr, "--- Loop #%d ---\n", i);
175 fflush(stderr);
176
177 _testembed_Py_InitializeFromConfig();
178 int err = PyRun_SimpleString(code);
179 Py_Finalize();
180 if (err) {
181 return 1;
182 }
183 }
184 return 0;
185 }
186
187 /****************************************************************************
188 * Test the Py_Initialize(Ex) convenience/compatibility wrappers
189 ***************************************************************************/
190 // This is here to help ensure there are no wrapper resource leaks (gh-96853)
test_repeated_simple_init(void)191 static int test_repeated_simple_init(void)
192 {
193 for (int i=1; i <= INIT_LOOPS; i++) {
194 fprintf(stderr, "--- Loop #%d ---\n", i);
195 fflush(stderr);
196
197 _testembed_Py_Initialize();
198 Py_Finalize();
199 printf("Finalized\n"); // Give test_embed some output to check
200 }
201 return 0;
202 }
203
204
205 /*****************************************************
206 * Test forcing a particular IO encoding
207 *****************************************************/
208
check_stdio_details(const char * encoding,const char * errors)209 static void check_stdio_details(const char *encoding, const char * errors)
210 {
211 /* Output info for the test case to check */
212 if (encoding) {
213 printf("Expected encoding: %s\n", encoding);
214 } else {
215 printf("Expected encoding: default\n");
216 }
217 if (errors) {
218 printf("Expected errors: %s\n", errors);
219 } else {
220 printf("Expected errors: default\n");
221 }
222 fflush(stdout);
223 /* Force the given IO encoding */
224 Py_SetStandardStreamEncoding(encoding, errors);
225 _testembed_Py_InitializeFromConfig();
226 PyRun_SimpleString(
227 "import sys;"
228 "print('stdin: {0.encoding}:{0.errors}'.format(sys.stdin));"
229 "print('stdout: {0.encoding}:{0.errors}'.format(sys.stdout));"
230 "print('stderr: {0.encoding}:{0.errors}'.format(sys.stderr));"
231 "sys.stdout.flush()"
232 );
233 Py_Finalize();
234 }
235
test_forced_io_encoding(void)236 static int test_forced_io_encoding(void)
237 {
238 /* Check various combinations */
239 printf("--- Use defaults ---\n");
240 check_stdio_details(NULL, NULL);
241 printf("--- Set errors only ---\n");
242 check_stdio_details(NULL, "ignore");
243 printf("--- Set encoding only ---\n");
244 check_stdio_details("iso8859-1", NULL);
245 printf("--- Set encoding and errors ---\n");
246 check_stdio_details("iso8859-1", "replace");
247
248 /* Check calling after initialization fails */
249 Py_Initialize();
250
251 if (Py_SetStandardStreamEncoding(NULL, NULL) == 0) {
252 printf("Unexpected success calling Py_SetStandardStreamEncoding");
253 }
254 Py_Finalize();
255 return 0;
256 }
257
258 /*********************************************************
259 * Test parts of the C-API that work before initialization
260 *********************************************************/
261
262 /* The pre-initialization tests tend to break by segfaulting, so explicitly
263 * flushed progress messages make the broken API easier to find when they fail.
264 */
265 #define _Py_EMBED_PREINIT_CHECK(msg) \
266 do {printf(msg); fflush(stdout);} while (0);
267
test_pre_initialization_api(void)268 static int test_pre_initialization_api(void)
269 {
270 /* the test doesn't support custom memory allocators */
271 putenv("PYTHONMALLOC=");
272
273 /* Leading "./" ensures getpath.c can still find the standard library */
274 _Py_EMBED_PREINIT_CHECK("Checking Py_DecodeLocale\n");
275 wchar_t *program = Py_DecodeLocale("./spam", NULL);
276 if (program == NULL) {
277 fprintf(stderr, "Fatal error: cannot decode program name\n");
278 return 1;
279 }
280 _Py_EMBED_PREINIT_CHECK("Checking Py_SetProgramName\n");
281 Py_SetProgramName(program);
282
283 _Py_EMBED_PREINIT_CHECK("Initializing interpreter\n");
284 Py_Initialize();
285 _Py_EMBED_PREINIT_CHECK("Check sys module contents\n");
286 PyRun_SimpleString("import sys; "
287 "print('sys.executable:', sys.executable)");
288 _Py_EMBED_PREINIT_CHECK("Finalizing interpreter\n");
289 Py_Finalize();
290
291 _Py_EMBED_PREINIT_CHECK("Freeing memory allocated by Py_DecodeLocale\n");
292 PyMem_RawFree(program);
293 return 0;
294 }
295
296
297 /* bpo-33042: Ensure embedding apps can predefine sys module options */
test_pre_initialization_sys_options(void)298 static int test_pre_initialization_sys_options(void)
299 {
300 /* We allocate a couple of the options dynamically, and then delete
301 * them before calling Py_Initialize. This ensures the interpreter isn't
302 * relying on the caller to keep the passed in strings alive.
303 */
304 const wchar_t *static_warnoption = L"once";
305 const wchar_t *static_xoption = L"also_not_an_option=2";
306 size_t warnoption_len = wcslen(static_warnoption);
307 size_t xoption_len = wcslen(static_xoption);
308 wchar_t *dynamic_once_warnoption = \
309 (wchar_t *) calloc(warnoption_len+1, sizeof(wchar_t));
310 wchar_t *dynamic_xoption = \
311 (wchar_t *) calloc(xoption_len+1, sizeof(wchar_t));
312 wcsncpy(dynamic_once_warnoption, static_warnoption, warnoption_len+1);
313 wcsncpy(dynamic_xoption, static_xoption, xoption_len+1);
314
315 _Py_EMBED_PREINIT_CHECK("Checking PySys_AddWarnOption\n");
316 PySys_AddWarnOption(L"default");
317 _Py_EMBED_PREINIT_CHECK("Checking PySys_ResetWarnOptions\n");
318 PySys_ResetWarnOptions();
319 _Py_EMBED_PREINIT_CHECK("Checking PySys_AddWarnOption linked list\n");
320 PySys_AddWarnOption(dynamic_once_warnoption);
321 PySys_AddWarnOption(L"module");
322 PySys_AddWarnOption(L"default");
323 _Py_EMBED_PREINIT_CHECK("Checking PySys_AddXOption\n");
324 PySys_AddXOption(L"not_an_option=1");
325 PySys_AddXOption(dynamic_xoption);
326
327 /* Delete the dynamic options early */
328 free(dynamic_once_warnoption);
329 dynamic_once_warnoption = NULL;
330 free(dynamic_xoption);
331 dynamic_xoption = NULL;
332
333 _Py_EMBED_PREINIT_CHECK("Initializing interpreter\n");
334 _testembed_Py_InitializeFromConfig();
335 _Py_EMBED_PREINIT_CHECK("Check sys module contents\n");
336 PyRun_SimpleString("import sys; "
337 "print('sys.warnoptions:', sys.warnoptions); "
338 "print('sys._xoptions:', sys._xoptions); "
339 "warnings = sys.modules['warnings']; "
340 "latest_filters = [f[0] for f in warnings.filters[:3]]; "
341 "print('warnings.filters[:3]:', latest_filters)");
342 _Py_EMBED_PREINIT_CHECK("Finalizing interpreter\n");
343 Py_Finalize();
344
345 return 0;
346 }
347
348
349 /* bpo-20891: Avoid race condition when initialising the GIL */
bpo20891_thread(void * lockp)350 static void bpo20891_thread(void *lockp)
351 {
352 PyThread_type_lock lock = *((PyThread_type_lock*)lockp);
353
354 PyGILState_STATE state = PyGILState_Ensure();
355 if (!PyGILState_Check()) {
356 error("PyGILState_Check failed!");
357 abort();
358 }
359
360 PyGILState_Release(state);
361
362 PyThread_release_lock(lock);
363 }
364
test_bpo20891(void)365 static int test_bpo20891(void)
366 {
367 /* the test doesn't support custom memory allocators */
368 putenv("PYTHONMALLOC=");
369
370 /* bpo-20891: Calling PyGILState_Ensure in a non-Python thread must not
371 crash. */
372 PyThread_type_lock lock = PyThread_allocate_lock();
373 if (!lock) {
374 error("PyThread_allocate_lock failed!");
375 return 1;
376 }
377
378 _testembed_Py_InitializeFromConfig();
379
380 unsigned long thrd = PyThread_start_new_thread(bpo20891_thread, &lock);
381 if (thrd == PYTHREAD_INVALID_THREAD_ID) {
382 error("PyThread_start_new_thread failed!");
383 return 1;
384 }
385 PyThread_acquire_lock(lock, WAIT_LOCK);
386
387 Py_BEGIN_ALLOW_THREADS
388 /* wait until the thread exit */
389 PyThread_acquire_lock(lock, WAIT_LOCK);
390 Py_END_ALLOW_THREADS
391
392 PyThread_free_lock(lock);
393
394 Py_Finalize();
395
396 return 0;
397 }
398
test_initialize_twice(void)399 static int test_initialize_twice(void)
400 {
401 _testembed_Py_InitializeFromConfig();
402
403 /* bpo-33932: Calling Py_Initialize() twice should do nothing
404 * (and not crash!). */
405 Py_Initialize();
406
407 Py_Finalize();
408
409 return 0;
410 }
411
test_initialize_pymain(void)412 static int test_initialize_pymain(void)
413 {
414 wchar_t *argv[] = {L"PYTHON", L"-c",
415 (L"import sys; "
416 L"print(f'Py_Main() after Py_Initialize: "
417 L"sys.argv={sys.argv}')"),
418 L"arg2"};
419 _testembed_Py_InitializeFromConfig();
420
421 /* bpo-34008: Calling Py_Main() after Py_Initialize() must not crash */
422 Py_Main(Py_ARRAY_LENGTH(argv), argv);
423
424 Py_Finalize();
425
426 return 0;
427 }
428
429
430 static void
dump_config(void)431 dump_config(void)
432 {
433 (void) PyRun_SimpleStringFlags(
434 "import _testinternalcapi, json; "
435 "print(json.dumps(_testinternalcapi.get_configs()))",
436 0);
437 }
438
439
test_init_initialize_config(void)440 static int test_init_initialize_config(void)
441 {
442 _testembed_Py_InitializeFromConfig();
443 dump_config();
444 Py_Finalize();
445 return 0;
446 }
447
448
config_set_argv(PyConfig * config,Py_ssize_t argc,wchar_t * const * argv)449 static void config_set_argv(PyConfig *config, Py_ssize_t argc, wchar_t * const *argv)
450 {
451 PyStatus status = PyConfig_SetArgv(config, argc, argv);
452 if (PyStatus_Exception(status)) {
453 PyConfig_Clear(config);
454 Py_ExitStatusException(status);
455 }
456 }
457
458
459 static void
config_set_wide_string_list(PyConfig * config,PyWideStringList * list,Py_ssize_t length,wchar_t ** items)460 config_set_wide_string_list(PyConfig *config, PyWideStringList *list,
461 Py_ssize_t length, wchar_t **items)
462 {
463 PyStatus status = PyConfig_SetWideStringList(config, list, length, items);
464 if (PyStatus_Exception(status)) {
465 PyConfig_Clear(config);
466 Py_ExitStatusException(status);
467 }
468 }
469
470
check_init_compat_config(int preinit)471 static int check_init_compat_config(int preinit)
472 {
473 PyStatus status;
474
475 if (preinit) {
476 PyPreConfig preconfig;
477 _PyPreConfig_InitCompatConfig(&preconfig);
478
479 status = Py_PreInitialize(&preconfig);
480 if (PyStatus_Exception(status)) {
481 Py_ExitStatusException(status);
482 }
483 }
484
485 PyConfig config;
486 _PyConfig_InitCompatConfig(&config);
487
488 config_set_program_name(&config);
489 init_from_config_clear(&config);
490
491 dump_config();
492 Py_Finalize();
493 return 0;
494 }
495
496
test_preinit_compat_config(void)497 static int test_preinit_compat_config(void)
498 {
499 return check_init_compat_config(1);
500 }
501
502
test_init_compat_config(void)503 static int test_init_compat_config(void)
504 {
505 return check_init_compat_config(0);
506 }
507
508
test_init_global_config(void)509 static int test_init_global_config(void)
510 {
511 /* FIXME: test Py_IgnoreEnvironmentFlag */
512
513 putenv("PYTHONUTF8=0");
514 Py_UTF8Mode = 1;
515
516 /* Test initialization from global configuration variables (Py_xxx) */
517 Py_SetProgramName(L"./globalvar");
518
519 /* Py_IsolatedFlag is not tested */
520 Py_NoSiteFlag = 1;
521 Py_BytesWarningFlag = 1;
522
523 putenv("PYTHONINSPECT=");
524 Py_InspectFlag = 1;
525
526 putenv("PYTHONOPTIMIZE=0");
527 Py_InteractiveFlag = 1;
528
529 putenv("PYTHONDEBUG=0");
530 Py_OptimizeFlag = 2;
531
532 /* Py_DebugFlag is not tested */
533
534 putenv("PYTHONDONTWRITEBYTECODE=");
535 Py_DontWriteBytecodeFlag = 1;
536
537 putenv("PYTHONVERBOSE=0");
538 Py_VerboseFlag = 1;
539
540 Py_QuietFlag = 1;
541 Py_NoUserSiteDirectory = 1;
542
543 putenv("PYTHONUNBUFFERED=");
544 Py_UnbufferedStdioFlag = 1;
545
546 Py_FrozenFlag = 1;
547
548 /* FIXME: test Py_LegacyWindowsFSEncodingFlag */
549 /* FIXME: test Py_LegacyWindowsStdioFlag */
550
551 Py_Initialize();
552 dump_config();
553 Py_Finalize();
554 return 0;
555 }
556
557
test_init_from_config(void)558 static int test_init_from_config(void)
559 {
560 PyPreConfig preconfig;
561 _PyPreConfig_InitCompatConfig(&preconfig);
562
563 putenv("PYTHONMALLOC=malloc_debug");
564 preconfig.allocator = PYMEM_ALLOCATOR_MALLOC;
565
566 putenv("PYTHONUTF8=0");
567 Py_UTF8Mode = 0;
568 preconfig.utf8_mode = 1;
569
570 PyStatus status = Py_PreInitialize(&preconfig);
571 if (PyStatus_Exception(status)) {
572 Py_ExitStatusException(status);
573 }
574
575 PyConfig config;
576 _PyConfig_InitCompatConfig(&config);
577
578 config.install_signal_handlers = 0;
579
580 /* FIXME: test use_environment */
581
582 putenv("PYTHONHASHSEED=42");
583 config.use_hash_seed = 1;
584 config.hash_seed = 123;
585
586 /* dev_mode=1 is tested in test_init_dev_mode() */
587
588 putenv("PYTHONFAULTHANDLER=");
589 config.faulthandler = 1;
590
591 putenv("PYTHONTRACEMALLOC=0");
592 config.tracemalloc = 2;
593
594 putenv("PYTHONPROFILEIMPORTTIME=0");
595 config.import_time = 1;
596
597 putenv("PYTHONNODEBUGRANGES=0");
598 config.code_debug_ranges = 0;
599
600 config.show_ref_count = 1;
601 /* FIXME: test dump_refs: bpo-34223 */
602
603 putenv("PYTHONMALLOCSTATS=0");
604 config.malloc_stats = 1;
605
606 putenv("PYTHONPYCACHEPREFIX=env_pycache_prefix");
607 config_set_string(&config, &config.pycache_prefix, L"conf_pycache_prefix");
608
609 Py_SetProgramName(L"./globalvar");
610 config_set_string(&config, &config.program_name, L"./conf_program_name");
611
612 wchar_t* argv[] = {
613 L"python3",
614 L"-W",
615 L"cmdline_warnoption",
616 L"-X",
617 L"cmdline_xoption",
618 L"-c",
619 L"pass",
620 L"arg2",
621 };
622 config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
623 config.parse_argv = 1;
624
625 wchar_t* xoptions[3] = {
626 L"config_xoption1=3",
627 L"config_xoption2=",
628 L"config_xoption3",
629 };
630 config_set_wide_string_list(&config, &config.xoptions,
631 Py_ARRAY_LENGTH(xoptions), xoptions);
632
633 wchar_t* warnoptions[1] = {
634 L"config_warnoption",
635 };
636 config_set_wide_string_list(&config, &config.warnoptions,
637 Py_ARRAY_LENGTH(warnoptions), warnoptions);
638
639 /* FIXME: test pythonpath_env */
640 /* FIXME: test home */
641 /* FIXME: test path config: module_search_path .. dll_path */
642
643 putenv("PYTHONPLATLIBDIR=env_platlibdir");
644 status = PyConfig_SetBytesString(&config, &config.platlibdir, "my_platlibdir");
645 if (PyStatus_Exception(status)) {
646 PyConfig_Clear(&config);
647 Py_ExitStatusException(status);
648 }
649
650 putenv("PYTHONVERBOSE=0");
651 Py_VerboseFlag = 0;
652 config.verbose = 1;
653
654 Py_NoSiteFlag = 0;
655 config.site_import = 0;
656
657 Py_BytesWarningFlag = 0;
658 config.bytes_warning = 1;
659
660 putenv("PYTHONINSPECT=");
661 Py_InspectFlag = 0;
662 config.inspect = 1;
663
664 Py_InteractiveFlag = 0;
665 config.interactive = 1;
666
667 putenv("PYTHONOPTIMIZE=0");
668 Py_OptimizeFlag = 1;
669 config.optimization_level = 2;
670
671 /* FIXME: test parser_debug */
672
673 putenv("PYTHONDONTWRITEBYTECODE=");
674 Py_DontWriteBytecodeFlag = 0;
675 config.write_bytecode = 0;
676
677 Py_QuietFlag = 0;
678 config.quiet = 1;
679
680 config.configure_c_stdio = 1;
681
682 putenv("PYTHONUNBUFFERED=");
683 Py_UnbufferedStdioFlag = 0;
684 config.buffered_stdio = 0;
685
686 putenv("PYTHONIOENCODING=cp424");
687 Py_SetStandardStreamEncoding("ascii", "ignore");
688 #ifdef MS_WINDOWS
689 /* Py_SetStandardStreamEncoding() sets Py_LegacyWindowsStdioFlag to 1.
690 Force it to 0 through the config. */
691 config.legacy_windows_stdio = 0;
692 #endif
693 config_set_string(&config, &config.stdio_encoding, L"iso8859-1");
694 config_set_string(&config, &config.stdio_errors, L"replace");
695
696 putenv("PYTHONNOUSERSITE=");
697 Py_NoUserSiteDirectory = 0;
698 config.user_site_directory = 0;
699
700 config_set_string(&config, &config.check_hash_pycs_mode, L"always");
701
702 Py_FrozenFlag = 0;
703 config.pathconfig_warnings = 0;
704
705 config.safe_path = 1;
706
707 config._isolated_interpreter = 1;
708
709 init_from_config_clear(&config);
710
711 dump_config();
712 Py_Finalize();
713 return 0;
714 }
715
716
check_init_parse_argv(int parse_argv)717 static int check_init_parse_argv(int parse_argv)
718 {
719 PyConfig config;
720 PyConfig_InitPythonConfig(&config);
721
722 config.parse_argv = parse_argv;
723
724 wchar_t* argv[] = {
725 L"./argv0",
726 L"-E",
727 L"-c",
728 L"pass",
729 L"arg1",
730 L"-v",
731 L"arg3",
732 };
733 config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
734 init_from_config_clear(&config);
735
736 dump_config();
737 Py_Finalize();
738 return 0;
739 }
740
741
test_init_parse_argv(void)742 static int test_init_parse_argv(void)
743 {
744 return check_init_parse_argv(1);
745 }
746
747
test_init_dont_parse_argv(void)748 static int test_init_dont_parse_argv(void)
749 {
750 return check_init_parse_argv(0);
751 }
752
753
set_most_env_vars(void)754 static void set_most_env_vars(void)
755 {
756 putenv("PYTHONHASHSEED=42");
757 putenv("PYTHONMALLOC=malloc");
758 putenv("PYTHONTRACEMALLOC=2");
759 putenv("PYTHONPROFILEIMPORTTIME=1");
760 putenv("PYTHONNODEBUGRANGES=1");
761 putenv("PYTHONMALLOCSTATS=1");
762 putenv("PYTHONUTF8=1");
763 putenv("PYTHONVERBOSE=1");
764 putenv("PYTHONINSPECT=1");
765 putenv("PYTHONOPTIMIZE=2");
766 putenv("PYTHONDONTWRITEBYTECODE=1");
767 putenv("PYTHONUNBUFFERED=1");
768 putenv("PYTHONPYCACHEPREFIX=env_pycache_prefix");
769 putenv("PYTHONNOUSERSITE=1");
770 putenv("PYTHONFAULTHANDLER=1");
771 putenv("PYTHONIOENCODING=iso8859-1:replace");
772 putenv("PYTHONPLATLIBDIR=env_platlibdir");
773 putenv("PYTHONSAFEPATH=1");
774 }
775
776
set_all_env_vars(void)777 static void set_all_env_vars(void)
778 {
779 set_most_env_vars();
780
781 putenv("PYTHONWARNINGS=EnvVar");
782 putenv("PYTHONPATH=/my/path");
783 }
784
785
test_init_compat_env(void)786 static int test_init_compat_env(void)
787 {
788 /* Test initialization from environment variables */
789 Py_IgnoreEnvironmentFlag = 0;
790 set_all_env_vars();
791 _testembed_Py_InitializeFromConfig();
792 dump_config();
793 Py_Finalize();
794 return 0;
795 }
796
797
test_init_python_env(void)798 static int test_init_python_env(void)
799 {
800 set_all_env_vars();
801
802 PyConfig config;
803 PyConfig_InitPythonConfig(&config);
804
805 config_set_program_name(&config);
806 init_from_config_clear(&config);
807
808 dump_config();
809 Py_Finalize();
810 return 0;
811 }
812
813
set_all_env_vars_dev_mode(void)814 static void set_all_env_vars_dev_mode(void)
815 {
816 putenv("PYTHONMALLOC=");
817 putenv("PYTHONFAULTHANDLER=");
818 putenv("PYTHONDEVMODE=1");
819 }
820
821
test_init_env_dev_mode(void)822 static int test_init_env_dev_mode(void)
823 {
824 /* Test initialization from environment variables */
825 Py_IgnoreEnvironmentFlag = 0;
826 set_all_env_vars_dev_mode();
827 _testembed_Py_InitializeFromConfig();
828 dump_config();
829 Py_Finalize();
830 return 0;
831 }
832
833
test_init_env_dev_mode_alloc(void)834 static int test_init_env_dev_mode_alloc(void)
835 {
836 /* Test initialization from environment variables */
837 Py_IgnoreEnvironmentFlag = 0;
838 set_all_env_vars_dev_mode();
839 putenv("PYTHONMALLOC=malloc");
840 _testembed_Py_InitializeFromConfig();
841 dump_config();
842 Py_Finalize();
843 return 0;
844 }
845
846
test_init_isolated_flag(void)847 static int test_init_isolated_flag(void)
848 {
849 /* Test PyConfig.isolated=1 */
850 PyConfig config;
851 PyConfig_InitPythonConfig(&config);
852
853 Py_IsolatedFlag = 0;
854 config.isolated = 1;
855 // These options are set to 1 by isolated=1
856 config.safe_path = 0;
857 config.use_environment = 1;
858 config.user_site_directory = 1;
859
860 config_set_program_name(&config);
861 set_all_env_vars();
862 init_from_config_clear(&config);
863
864 dump_config();
865 Py_Finalize();
866 return 0;
867 }
868
869
870 /* PyPreConfig.isolated=1, PyConfig.isolated=0 */
test_preinit_isolated1(void)871 static int test_preinit_isolated1(void)
872 {
873 PyPreConfig preconfig;
874 _PyPreConfig_InitCompatConfig(&preconfig);
875
876 preconfig.isolated = 1;
877
878 PyStatus status = Py_PreInitialize(&preconfig);
879 if (PyStatus_Exception(status)) {
880 Py_ExitStatusException(status);
881 }
882
883 PyConfig config;
884 _PyConfig_InitCompatConfig(&config);
885
886 config_set_program_name(&config);
887 set_all_env_vars();
888 init_from_config_clear(&config);
889
890 dump_config();
891 Py_Finalize();
892 return 0;
893 }
894
895
896 /* PyPreConfig.isolated=0, PyConfig.isolated=1 */
test_preinit_isolated2(void)897 static int test_preinit_isolated2(void)
898 {
899 PyPreConfig preconfig;
900 _PyPreConfig_InitCompatConfig(&preconfig);
901
902 preconfig.isolated = 0;
903
904 PyStatus status = Py_PreInitialize(&preconfig);
905 if (PyStatus_Exception(status)) {
906 Py_ExitStatusException(status);
907 }
908
909 /* Test PyConfig.isolated=1 */
910 PyConfig config;
911 _PyConfig_InitCompatConfig(&config);
912
913 Py_IsolatedFlag = 0;
914 config.isolated = 1;
915
916 config_set_program_name(&config);
917 set_all_env_vars();
918 init_from_config_clear(&config);
919
920 dump_config();
921 Py_Finalize();
922 return 0;
923 }
924
925
test_preinit_dont_parse_argv(void)926 static int test_preinit_dont_parse_argv(void)
927 {
928 PyPreConfig preconfig;
929 PyPreConfig_InitIsolatedConfig(&preconfig);
930
931 preconfig.isolated = 0;
932
933 /* -X dev must be ignored by isolated preconfiguration */
934 wchar_t *argv[] = {L"python3",
935 L"-E",
936 L"-I",
937 L"-P",
938 L"-X", L"dev",
939 L"-X", L"utf8",
940 L"script.py"};
941 PyStatus status = Py_PreInitializeFromArgs(&preconfig,
942 Py_ARRAY_LENGTH(argv), argv);
943 if (PyStatus_Exception(status)) {
944 Py_ExitStatusException(status);
945 }
946
947 PyConfig config;
948 PyConfig_InitIsolatedConfig(&config);
949
950 config.isolated = 0;
951
952 /* Pre-initialize implicitly using argv: make sure that -X dev
953 is used to configure the allocation in preinitialization */
954 config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
955 config_set_program_name(&config);
956 init_from_config_clear(&config);
957
958 dump_config();
959 Py_Finalize();
960 return 0;
961 }
962
963
test_preinit_parse_argv(void)964 static int test_preinit_parse_argv(void)
965 {
966 PyConfig config;
967 PyConfig_InitPythonConfig(&config);
968
969 /* Pre-initialize implicitly using argv: make sure that -X dev
970 is used to configure the allocation in preinitialization */
971 wchar_t *argv[] = {L"python3", L"-X", L"dev", L"-P", L"script.py"};
972 config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
973 config_set_program_name(&config);
974 init_from_config_clear(&config);
975
976 dump_config();
977 Py_Finalize();
978 return 0;
979 }
980
981
982
983
set_all_global_config_variables(void)984 static void set_all_global_config_variables(void)
985 {
986 Py_IsolatedFlag = 0;
987 Py_IgnoreEnvironmentFlag = 0;
988 Py_BytesWarningFlag = 2;
989 Py_InspectFlag = 1;
990 Py_InteractiveFlag = 1;
991 Py_OptimizeFlag = 1;
992 Py_DebugFlag = 1;
993 Py_VerboseFlag = 1;
994 Py_QuietFlag = 1;
995 Py_FrozenFlag = 0;
996 Py_UnbufferedStdioFlag = 1;
997 Py_NoSiteFlag = 1;
998 Py_DontWriteBytecodeFlag = 1;
999 Py_NoUserSiteDirectory = 1;
1000 #ifdef MS_WINDOWS
1001 Py_LegacyWindowsStdioFlag = 1;
1002 #endif
1003 }
1004
1005
check_preinit_isolated_config(int preinit)1006 static int check_preinit_isolated_config(int preinit)
1007 {
1008 PyStatus status;
1009 PyPreConfig *rt_preconfig;
1010
1011 /* environment variables must be ignored */
1012 set_all_env_vars();
1013
1014 /* global configuration variables must be ignored */
1015 set_all_global_config_variables();
1016
1017 if (preinit) {
1018 PyPreConfig preconfig;
1019 PyPreConfig_InitIsolatedConfig(&preconfig);
1020
1021 status = Py_PreInitialize(&preconfig);
1022 if (PyStatus_Exception(status)) {
1023 Py_ExitStatusException(status);
1024 }
1025
1026 rt_preconfig = &_PyRuntime.preconfig;
1027 assert(rt_preconfig->isolated == 1);
1028 assert(rt_preconfig->use_environment == 0);
1029 }
1030
1031 PyConfig config;
1032 PyConfig_InitIsolatedConfig(&config);
1033
1034 config_set_program_name(&config);
1035 init_from_config_clear(&config);
1036
1037 rt_preconfig = &_PyRuntime.preconfig;
1038 assert(rt_preconfig->isolated == 1);
1039 assert(rt_preconfig->use_environment == 0);
1040
1041 dump_config();
1042 Py_Finalize();
1043 return 0;
1044 }
1045
1046
test_preinit_isolated_config(void)1047 static int test_preinit_isolated_config(void)
1048 {
1049 return check_preinit_isolated_config(1);
1050 }
1051
1052
test_init_isolated_config(void)1053 static int test_init_isolated_config(void)
1054 {
1055 return check_preinit_isolated_config(0);
1056 }
1057
1058
check_init_python_config(int preinit)1059 static int check_init_python_config(int preinit)
1060 {
1061 /* global configuration variables must be ignored */
1062 set_all_global_config_variables();
1063 Py_IsolatedFlag = 1;
1064 Py_IgnoreEnvironmentFlag = 1;
1065 Py_FrozenFlag = 1;
1066 Py_UnbufferedStdioFlag = 1;
1067 Py_NoSiteFlag = 1;
1068 Py_DontWriteBytecodeFlag = 1;
1069 Py_NoUserSiteDirectory = 1;
1070 #ifdef MS_WINDOWS
1071 Py_LegacyWindowsStdioFlag = 1;
1072 #endif
1073
1074 if (preinit) {
1075 PyPreConfig preconfig;
1076 PyPreConfig_InitPythonConfig(&preconfig);
1077
1078 PyStatus status = Py_PreInitialize(&preconfig);
1079 if (PyStatus_Exception(status)) {
1080 Py_ExitStatusException(status);
1081 }
1082 }
1083
1084 PyConfig config;
1085 PyConfig_InitPythonConfig(&config);
1086
1087 config_set_program_name(&config);
1088 init_from_config_clear(&config);
1089
1090 dump_config();
1091 Py_Finalize();
1092 return 0;
1093 }
1094
1095
test_preinit_python_config(void)1096 static int test_preinit_python_config(void)
1097 {
1098 return check_init_python_config(1);
1099 }
1100
1101
test_init_python_config(void)1102 static int test_init_python_config(void)
1103 {
1104 return check_init_python_config(0);
1105 }
1106
1107
test_init_dont_configure_locale(void)1108 static int test_init_dont_configure_locale(void)
1109 {
1110 PyPreConfig preconfig;
1111 PyPreConfig_InitPythonConfig(&preconfig);
1112
1113 preconfig.configure_locale = 0;
1114 preconfig.coerce_c_locale = 1;
1115 preconfig.coerce_c_locale_warn = 1;
1116
1117 PyStatus status = Py_PreInitialize(&preconfig);
1118 if (PyStatus_Exception(status)) {
1119 Py_ExitStatusException(status);
1120 }
1121
1122 PyConfig config;
1123 PyConfig_InitPythonConfig(&config);
1124
1125 config_set_program_name(&config);
1126 init_from_config_clear(&config);
1127
1128 dump_config();
1129 Py_Finalize();
1130 return 0;
1131 }
1132
1133
test_init_dev_mode(void)1134 static int test_init_dev_mode(void)
1135 {
1136 PyConfig config;
1137 PyConfig_InitPythonConfig(&config);
1138
1139 putenv("PYTHONFAULTHANDLER=");
1140 putenv("PYTHONMALLOC=");
1141 config.dev_mode = 1;
1142 config_set_program_name(&config);
1143 init_from_config_clear(&config);
1144
1145 dump_config();
1146 Py_Finalize();
1147 return 0;
1148 }
1149
_open_code_hook(PyObject * path,void * data)1150 static PyObject *_open_code_hook(PyObject *path, void *data)
1151 {
1152 if (PyUnicode_CompareWithASCIIString(path, "$$test-filename") == 0) {
1153 return PyLong_FromVoidPtr(data);
1154 }
1155 PyObject *io = PyImport_ImportModule("_io");
1156 if (!io) {
1157 return NULL;
1158 }
1159 return PyObject_CallMethod(io, "open", "Os", path, "rb");
1160 }
1161
test_open_code_hook(void)1162 static int test_open_code_hook(void)
1163 {
1164 int result = 0;
1165
1166 /* Provide a hook */
1167 result = PyFile_SetOpenCodeHook(_open_code_hook, &result);
1168 if (result) {
1169 printf("Failed to set hook\n");
1170 return 1;
1171 }
1172 /* A second hook should fail */
1173 result = PyFile_SetOpenCodeHook(_open_code_hook, &result);
1174 if (!result) {
1175 printf("Should have failed to set second hook\n");
1176 return 2;
1177 }
1178
1179 Py_IgnoreEnvironmentFlag = 0;
1180 _testembed_Py_InitializeFromConfig();
1181 result = 0;
1182
1183 PyObject *r = PyFile_OpenCode("$$test-filename");
1184 if (!r) {
1185 PyErr_Print();
1186 result = 3;
1187 } else {
1188 void *cmp = PyLong_AsVoidPtr(r);
1189 Py_DECREF(r);
1190 if (cmp != &result) {
1191 printf("Did not get expected result from hook\n");
1192 result = 4;
1193 }
1194 }
1195
1196 if (!result) {
1197 PyObject *io = PyImport_ImportModule("_io");
1198 PyObject *r = io
1199 ? PyObject_CallMethod(io, "open_code", "s", "$$test-filename")
1200 : NULL;
1201 if (!r) {
1202 PyErr_Print();
1203 result = 5;
1204 } else {
1205 void *cmp = PyLong_AsVoidPtr(r);
1206 Py_DECREF(r);
1207 if (cmp != &result) {
1208 printf("Did not get expected result from hook\n");
1209 result = 6;
1210 }
1211 }
1212 Py_XDECREF(io);
1213 }
1214
1215 Py_Finalize();
1216 return result;
1217 }
1218
1219 static int _audit_hook_clear_count = 0;
1220
_audit_hook(const char * event,PyObject * args,void * userdata)1221 static int _audit_hook(const char *event, PyObject *args, void *userdata)
1222 {
1223 assert(args && PyTuple_CheckExact(args));
1224 if (strcmp(event, "_testembed.raise") == 0) {
1225 PyErr_SetString(PyExc_RuntimeError, "Intentional error");
1226 return -1;
1227 } else if (strcmp(event, "_testembed.set") == 0) {
1228 if (!PyArg_ParseTuple(args, "n", userdata)) {
1229 return -1;
1230 }
1231 return 0;
1232 } else if (strcmp(event, "cpython._PySys_ClearAuditHooks") == 0) {
1233 _audit_hook_clear_count += 1;
1234 }
1235 return 0;
1236 }
1237
_test_audit(Py_ssize_t setValue)1238 static int _test_audit(Py_ssize_t setValue)
1239 {
1240 Py_ssize_t sawSet = 0;
1241
1242 Py_IgnoreEnvironmentFlag = 0;
1243 PySys_AddAuditHook(_audit_hook, &sawSet);
1244 _testembed_Py_InitializeFromConfig();
1245
1246 if (PySys_Audit("_testembed.raise", NULL) == 0) {
1247 printf("No error raised");
1248 return 1;
1249 }
1250 if (PySys_Audit("_testembed.nop", NULL) != 0) {
1251 printf("Nop event failed");
1252 /* Exception from above may still remain */
1253 PyErr_Clear();
1254 return 2;
1255 }
1256 if (!PyErr_Occurred()) {
1257 printf("Exception not preserved");
1258 return 3;
1259 }
1260 PyErr_Clear();
1261
1262 if (PySys_Audit("_testembed.set", "n", setValue) != 0) {
1263 PyErr_Print();
1264 printf("Set event failed");
1265 return 4;
1266 }
1267
1268 if (sawSet != 42) {
1269 printf("Failed to see *userData change\n");
1270 return 5;
1271 }
1272 return 0;
1273 }
1274
test_audit(void)1275 static int test_audit(void)
1276 {
1277 int result = _test_audit(42);
1278 Py_Finalize();
1279 if (_audit_hook_clear_count != 1) {
1280 return 0x1000 | _audit_hook_clear_count;
1281 }
1282 return result;
1283 }
1284
1285 static volatile int _audit_subinterpreter_interpreter_count = 0;
1286
_audit_subinterpreter_hook(const char * event,PyObject * args,void * userdata)1287 static int _audit_subinterpreter_hook(const char *event, PyObject *args, void *userdata)
1288 {
1289 printf("%s\n", event);
1290 if (strcmp(event, "cpython.PyInterpreterState_New") == 0) {
1291 _audit_subinterpreter_interpreter_count += 1;
1292 }
1293 return 0;
1294 }
1295
test_audit_subinterpreter(void)1296 static int test_audit_subinterpreter(void)
1297 {
1298 Py_IgnoreEnvironmentFlag = 0;
1299 PySys_AddAuditHook(_audit_subinterpreter_hook, NULL);
1300 _testembed_Py_InitializeFromConfig();
1301
1302 Py_NewInterpreter();
1303 Py_NewInterpreter();
1304 Py_NewInterpreter();
1305
1306 Py_Finalize();
1307
1308 switch (_audit_subinterpreter_interpreter_count) {
1309 case 3: return 0;
1310 case 0: return -1;
1311 default: return _audit_subinterpreter_interpreter_count;
1312 }
1313 }
1314
1315 typedef struct {
1316 const char* expected;
1317 int exit;
1318 } AuditRunCommandTest;
1319
_audit_hook_run(const char * eventName,PyObject * args,void * userData)1320 static int _audit_hook_run(const char *eventName, PyObject *args, void *userData)
1321 {
1322 AuditRunCommandTest *test = (AuditRunCommandTest*)userData;
1323 if (strcmp(eventName, test->expected)) {
1324 return 0;
1325 }
1326
1327 if (test->exit) {
1328 PyObject *msg = PyUnicode_FromFormat("detected %s(%R)", eventName, args);
1329 if (msg) {
1330 printf("%s\n", PyUnicode_AsUTF8(msg));
1331 Py_DECREF(msg);
1332 }
1333 exit(test->exit);
1334 }
1335
1336 PyErr_Format(PyExc_RuntimeError, "detected %s(%R)", eventName, args);
1337 return -1;
1338 }
1339
test_audit_run_command(void)1340 static int test_audit_run_command(void)
1341 {
1342 AuditRunCommandTest test = {"cpython.run_command"};
1343 wchar_t *argv[] = {PROGRAM_NAME, L"-c", L"pass"};
1344
1345 Py_IgnoreEnvironmentFlag = 0;
1346 PySys_AddAuditHook(_audit_hook_run, (void*)&test);
1347
1348 return Py_Main(Py_ARRAY_LENGTH(argv), argv);
1349 }
1350
test_audit_run_file(void)1351 static int test_audit_run_file(void)
1352 {
1353 AuditRunCommandTest test = {"cpython.run_file"};
1354 wchar_t *argv[] = {PROGRAM_NAME, L"filename.py"};
1355
1356 Py_IgnoreEnvironmentFlag = 0;
1357 PySys_AddAuditHook(_audit_hook_run, (void*)&test);
1358
1359 return Py_Main(Py_ARRAY_LENGTH(argv), argv);
1360 }
1361
run_audit_run_test(int argc,wchar_t ** argv,void * test)1362 static int run_audit_run_test(int argc, wchar_t **argv, void *test)
1363 {
1364 PyConfig config;
1365 PyConfig_InitPythonConfig(&config);
1366
1367 config.argv.length = argc;
1368 config.argv.items = argv;
1369 config.parse_argv = 1;
1370 config.program_name = argv[0];
1371 config.interactive = 1;
1372 config.isolated = 0;
1373 config.use_environment = 1;
1374 config.quiet = 1;
1375
1376 PySys_AddAuditHook(_audit_hook_run, test);
1377
1378 PyStatus status = Py_InitializeFromConfig(&config);
1379 if (PyStatus_Exception(status)) {
1380 Py_ExitStatusException(status);
1381 }
1382
1383 return Py_RunMain();
1384 }
1385
test_audit_run_interactivehook(void)1386 static int test_audit_run_interactivehook(void)
1387 {
1388 AuditRunCommandTest test = {"cpython.run_interactivehook", 10};
1389 wchar_t *argv[] = {PROGRAM_NAME};
1390 return run_audit_run_test(Py_ARRAY_LENGTH(argv), argv, &test);
1391 }
1392
test_audit_run_startup(void)1393 static int test_audit_run_startup(void)
1394 {
1395 AuditRunCommandTest test = {"cpython.run_startup", 10};
1396 wchar_t *argv[] = {PROGRAM_NAME};
1397 return run_audit_run_test(Py_ARRAY_LENGTH(argv), argv, &test);
1398 }
1399
test_audit_run_stdin(void)1400 static int test_audit_run_stdin(void)
1401 {
1402 AuditRunCommandTest test = {"cpython.run_stdin"};
1403 wchar_t *argv[] = {PROGRAM_NAME};
1404 return run_audit_run_test(Py_ARRAY_LENGTH(argv), argv, &test);
1405 }
1406
test_init_read_set(void)1407 static int test_init_read_set(void)
1408 {
1409 PyStatus status;
1410 PyConfig config;
1411 PyConfig_InitPythonConfig(&config);
1412
1413 status = PyConfig_SetBytesString(&config, &config.program_name,
1414 "./init_read_set");
1415 if (PyStatus_Exception(status)) {
1416 goto fail;
1417 }
1418
1419 status = PyConfig_Read(&config);
1420 if (PyStatus_Exception(status)) {
1421 goto fail;
1422 }
1423
1424 status = PyWideStringList_Insert(&config.module_search_paths,
1425 1, L"test_path_insert1");
1426 if (PyStatus_Exception(status)) {
1427 goto fail;
1428 }
1429
1430 status = PyWideStringList_Append(&config.module_search_paths,
1431 L"test_path_append");
1432 if (PyStatus_Exception(status)) {
1433 goto fail;
1434 }
1435
1436 /* override executable computed by PyConfig_Read() */
1437 config_set_string(&config, &config.executable, L"my_executable");
1438 init_from_config_clear(&config);
1439
1440 dump_config();
1441 Py_Finalize();
1442 return 0;
1443
1444 fail:
1445 PyConfig_Clear(&config);
1446 Py_ExitStatusException(status);
1447 }
1448
1449
test_init_sys_add(void)1450 static int test_init_sys_add(void)
1451 {
1452 PySys_AddXOption(L"sysadd_xoption");
1453 PySys_AddXOption(L"faulthandler");
1454 PySys_AddWarnOption(L"ignore:::sysadd_warnoption");
1455
1456 PyConfig config;
1457 PyConfig_InitPythonConfig(&config);
1458
1459 wchar_t* argv[] = {
1460 L"python3",
1461 L"-W",
1462 L"ignore:::cmdline_warnoption",
1463 L"-X",
1464 L"cmdline_xoption",
1465 };
1466 config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
1467 config.parse_argv = 1;
1468
1469 PyStatus status;
1470 status = PyWideStringList_Append(&config.xoptions,
1471 L"config_xoption");
1472 if (PyStatus_Exception(status)) {
1473 goto fail;
1474 }
1475
1476 status = PyWideStringList_Append(&config.warnoptions,
1477 L"ignore:::config_warnoption");
1478 if (PyStatus_Exception(status)) {
1479 goto fail;
1480 }
1481
1482 config_set_program_name(&config);
1483 init_from_config_clear(&config);
1484
1485 dump_config();
1486 Py_Finalize();
1487 return 0;
1488
1489 fail:
1490 PyConfig_Clear(&config);
1491 Py_ExitStatusException(status);
1492 }
1493
1494
test_init_setpath(void)1495 static int test_init_setpath(void)
1496 {
1497 char *env = getenv("TESTPATH");
1498 if (!env) {
1499 error("missing TESTPATH env var");
1500 return 1;
1501 }
1502 wchar_t *path = Py_DecodeLocale(env, NULL);
1503 if (path == NULL) {
1504 error("failed to decode TESTPATH");
1505 return 1;
1506 }
1507 Py_SetPath(path);
1508 PyMem_RawFree(path);
1509 putenv("TESTPATH=");
1510
1511 Py_Initialize();
1512 dump_config();
1513 Py_Finalize();
1514 return 0;
1515 }
1516
1517
test_init_setpath_config(void)1518 static int test_init_setpath_config(void)
1519 {
1520 PyPreConfig preconfig;
1521 PyPreConfig_InitPythonConfig(&preconfig);
1522
1523 /* Explicitly preinitializes with Python preconfiguration to avoid
1524 Py_SetPath() implicit preinitialization with compat preconfiguration. */
1525 PyStatus status = Py_PreInitialize(&preconfig);
1526 if (PyStatus_Exception(status)) {
1527 Py_ExitStatusException(status);
1528 }
1529
1530 char *env = getenv("TESTPATH");
1531 if (!env) {
1532 error("missing TESTPATH env var");
1533 return 1;
1534 }
1535 wchar_t *path = Py_DecodeLocale(env, NULL);
1536 if (path == NULL) {
1537 error("failed to decode TESTPATH");
1538 return 1;
1539 }
1540 Py_SetPath(path);
1541 PyMem_RawFree(path);
1542 putenv("TESTPATH=");
1543
1544 PyConfig config;
1545 PyConfig_InitPythonConfig(&config);
1546
1547 config_set_string(&config, &config.program_name, L"conf_program_name");
1548 config_set_string(&config, &config.executable, L"conf_executable");
1549 init_from_config_clear(&config);
1550
1551 dump_config();
1552 Py_Finalize();
1553 return 0;
1554 }
1555
1556
test_init_setpythonhome(void)1557 static int test_init_setpythonhome(void)
1558 {
1559 char *env = getenv("TESTHOME");
1560 if (!env) {
1561 error("missing TESTHOME env var");
1562 return 1;
1563 }
1564 wchar_t *home = Py_DecodeLocale(env, NULL);
1565 if (home == NULL) {
1566 error("failed to decode TESTHOME");
1567 return 1;
1568 }
1569 Py_SetPythonHome(home);
1570 PyMem_RawFree(home);
1571 putenv("TESTHOME=");
1572
1573 Py_Initialize();
1574 dump_config();
1575 Py_Finalize();
1576 return 0;
1577 }
1578
1579
test_init_is_python_build(void)1580 static int test_init_is_python_build(void)
1581 {
1582 // gh-91985: in-tree builds fail to check for build directory landmarks
1583 // under the effect of 'home' or PYTHONHOME environment variable.
1584 char *env = getenv("TESTHOME");
1585 if (!env) {
1586 error("missing TESTHOME env var");
1587 return 1;
1588 }
1589 wchar_t *home = Py_DecodeLocale(env, NULL);
1590 if (home == NULL) {
1591 error("failed to decode TESTHOME");
1592 return 1;
1593 }
1594
1595 PyConfig config;
1596 _PyConfig_InitCompatConfig(&config);
1597 config_set_program_name(&config);
1598 config_set_string(&config, &config.home, home);
1599 PyMem_RawFree(home);
1600 putenv("TESTHOME=");
1601
1602 // Use an impossible value so we can detect whether it isn't updated
1603 // during initialization.
1604 config._is_python_build = INT_MAX;
1605 env = getenv("NEGATIVE_ISPYTHONBUILD");
1606 if (env && strcmp(env, "0") != 0) {
1607 config._is_python_build = INT_MIN;
1608 }
1609 init_from_config_clear(&config);
1610 Py_Finalize();
1611 // Second initialization
1612 config._is_python_build = -1;
1613 init_from_config_clear(&config);
1614 dump_config(); // home and _is_python_build are cached in _Py_path_config
1615 Py_Finalize();
1616 return 0;
1617 }
1618
1619
test_init_warnoptions(void)1620 static int test_init_warnoptions(void)
1621 {
1622 putenv("PYTHONWARNINGS=ignore:::env1,ignore:::env2");
1623
1624 PySys_AddWarnOption(L"ignore:::PySys_AddWarnOption1");
1625 PySys_AddWarnOption(L"ignore:::PySys_AddWarnOption2");
1626
1627 PyConfig config;
1628 PyConfig_InitPythonConfig(&config);
1629
1630 config.dev_mode = 1;
1631 config.bytes_warning = 1;
1632
1633 config_set_program_name(&config);
1634
1635 PyStatus status;
1636 status = PyWideStringList_Append(&config.warnoptions,
1637 L"ignore:::PyConfig_BeforeRead");
1638 if (PyStatus_Exception(status)) {
1639 Py_ExitStatusException(status);
1640 }
1641
1642 wchar_t* argv[] = {
1643 L"python3",
1644 L"-Wignore:::cmdline1",
1645 L"-Wignore:::cmdline2"};
1646 config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
1647 config.parse_argv = 1;
1648
1649 status = PyConfig_Read(&config);
1650 if (PyStatus_Exception(status)) {
1651 Py_ExitStatusException(status);
1652 }
1653
1654 status = PyWideStringList_Append(&config.warnoptions,
1655 L"ignore:::PyConfig_AfterRead");
1656 if (PyStatus_Exception(status)) {
1657 Py_ExitStatusException(status);
1658 }
1659
1660 status = PyWideStringList_Insert(&config.warnoptions,
1661 0, L"ignore:::PyConfig_Insert0");
1662 if (PyStatus_Exception(status)) {
1663 Py_ExitStatusException(status);
1664 }
1665
1666 init_from_config_clear(&config);
1667 dump_config();
1668 Py_Finalize();
1669 return 0;
1670 }
1671
1672
tune_config(void)1673 static int tune_config(void)
1674 {
1675 PyConfig config;
1676 PyConfig_InitPythonConfig(&config);
1677 if (_PyInterpreterState_GetConfigCopy(&config) < 0) {
1678 PyConfig_Clear(&config);
1679 PyErr_Print();
1680 return -1;
1681 }
1682
1683 config.bytes_warning = 2;
1684
1685 if (_PyInterpreterState_SetConfig(&config) < 0) {
1686 PyConfig_Clear(&config);
1687 return -1;
1688 }
1689 PyConfig_Clear(&config);
1690 return 0;
1691 }
1692
1693
test_init_set_config(void)1694 static int test_init_set_config(void)
1695 {
1696 // Initialize core
1697 PyConfig config;
1698 PyConfig_InitIsolatedConfig(&config);
1699 config_set_string(&config, &config.program_name, PROGRAM_NAME);
1700 config._init_main = 0;
1701 config.bytes_warning = 0;
1702 init_from_config_clear(&config);
1703
1704 // Tune the configuration using _PyInterpreterState_SetConfig()
1705 if (tune_config() < 0) {
1706 PyErr_Print();
1707 return 1;
1708 }
1709
1710 // Finish initialization: main part
1711 PyStatus status = _Py_InitializeMain();
1712 if (PyStatus_Exception(status)) {
1713 Py_ExitStatusException(status);
1714 }
1715
1716 dump_config();
1717 Py_Finalize();
1718 return 0;
1719 }
1720
1721
configure_init_main(PyConfig * config)1722 static void configure_init_main(PyConfig *config)
1723 {
1724 wchar_t* argv[] = {
1725 L"python3", L"-c",
1726 (L"import _testinternalcapi, json; "
1727 L"print(json.dumps(_testinternalcapi.get_configs()))"),
1728 L"arg2"};
1729
1730 config->parse_argv = 1;
1731
1732 config_set_argv(config, Py_ARRAY_LENGTH(argv), argv);
1733 config_set_string(config, &config->program_name, L"./python3");
1734 }
1735
1736
test_init_run_main(void)1737 static int test_init_run_main(void)
1738 {
1739 PyConfig config;
1740 PyConfig_InitPythonConfig(&config);
1741
1742 configure_init_main(&config);
1743 init_from_config_clear(&config);
1744
1745 return Py_RunMain();
1746 }
1747
1748
test_init_main(void)1749 static int test_init_main(void)
1750 {
1751 PyConfig config;
1752 PyConfig_InitPythonConfig(&config);
1753
1754 configure_init_main(&config);
1755 config._init_main = 0;
1756 init_from_config_clear(&config);
1757
1758 /* sys.stdout don't exist yet: it is created by _Py_InitializeMain() */
1759 int res = PyRun_SimpleString(
1760 "import sys; "
1761 "print('Run Python code before _Py_InitializeMain', "
1762 "file=sys.stderr)");
1763 if (res < 0) {
1764 exit(1);
1765 }
1766
1767 PyStatus status = _Py_InitializeMain();
1768 if (PyStatus_Exception(status)) {
1769 Py_ExitStatusException(status);
1770 }
1771
1772 return Py_RunMain();
1773 }
1774
1775
test_run_main(void)1776 static int test_run_main(void)
1777 {
1778 PyConfig config;
1779 PyConfig_InitPythonConfig(&config);
1780
1781 wchar_t *argv[] = {L"python3", L"-c",
1782 (L"import sys; "
1783 L"print(f'Py_RunMain(): sys.argv={sys.argv}')"),
1784 L"arg2"};
1785 config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
1786 config_set_string(&config, &config.program_name, L"./python3");
1787 init_from_config_clear(&config);
1788
1789 return Py_RunMain();
1790 }
1791
1792
test_run_main_loop(void)1793 static int test_run_main_loop(void)
1794 {
1795 // bpo-40413: Calling Py_InitializeFromConfig()+Py_RunMain() multiple
1796 // times must not crash.
1797 for (int i=0; i<5; i++) {
1798 int exitcode = test_run_main();
1799 if (exitcode != 0) {
1800 return exitcode;
1801 }
1802 }
1803 return 0;
1804 }
1805
1806
test_get_argc_argv(void)1807 static int test_get_argc_argv(void)
1808 {
1809 PyConfig config;
1810 PyConfig_InitPythonConfig(&config);
1811
1812 wchar_t *argv[] = {L"python3", L"-c", L"pass", L"arg2"};
1813 config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
1814 config_set_string(&config, &config.program_name, L"./python3");
1815
1816 // Calling PyConfig_Read() twice must not change Py_GetArgcArgv() result.
1817 // The second call is done by Py_InitializeFromConfig().
1818 PyStatus status = PyConfig_Read(&config);
1819 if (PyStatus_Exception(status)) {
1820 PyConfig_Clear(&config);
1821 Py_ExitStatusException(status);
1822 }
1823
1824 init_from_config_clear(&config);
1825
1826 int get_argc;
1827 wchar_t **get_argv;
1828 Py_GetArgcArgv(&get_argc, &get_argv);
1829 printf("argc: %i\n", get_argc);
1830 assert(get_argc == Py_ARRAY_LENGTH(argv));
1831 for (int i=0; i < get_argc; i++) {
1832 printf("argv[%i]: %ls\n", i, get_argv[i]);
1833 assert(wcscmp(get_argv[i], argv[i]) == 0);
1834 }
1835
1836 Py_Finalize();
1837
1838 printf("\n");
1839 printf("test ok\n");
1840 return 0;
1841 }
1842
1843
check_use_frozen_modules(const char * rawval)1844 static int check_use_frozen_modules(const char *rawval)
1845 {
1846 wchar_t optval[100];
1847 if (rawval == NULL) {
1848 wcscpy(optval, L"frozen_modules");
1849 }
1850 else if (swprintf(optval, 100,
1851 #if defined(_MSC_VER)
1852 L"frozen_modules=%S",
1853 #else
1854 L"frozen_modules=%s",
1855 #endif
1856 rawval) < 0) {
1857 error("rawval is too long");
1858 return -1;
1859 }
1860
1861 PyConfig config;
1862 PyConfig_InitPythonConfig(&config);
1863
1864 config.parse_argv = 1;
1865
1866 wchar_t* argv[] = {
1867 L"./argv0",
1868 L"-X",
1869 optval,
1870 L"-c",
1871 L"pass",
1872 };
1873 config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
1874 init_from_config_clear(&config);
1875
1876 dump_config();
1877 Py_Finalize();
1878 return 0;
1879 }
1880
test_init_use_frozen_modules(void)1881 static int test_init_use_frozen_modules(void)
1882 {
1883 const char *envvar = getenv("TESTFROZEN");
1884 return check_use_frozen_modules(envvar);
1885 }
1886
1887
test_unicode_id_init(void)1888 static int test_unicode_id_init(void)
1889 {
1890 // bpo-42882: Test that _PyUnicode_FromId() works
1891 // when Python is initialized multiples times.
1892 _Py_IDENTIFIER(test_unicode_id_init);
1893
1894 // Initialize Python once without using the identifier
1895 _testembed_Py_InitializeFromConfig();
1896 Py_Finalize();
1897
1898 // Now initialize Python multiple times and use the identifier.
1899 // The first _PyUnicode_FromId() call initializes the identifier index.
1900 for (int i=0; i<3; i++) {
1901 _testembed_Py_InitializeFromConfig();
1902
1903 PyObject *str1, *str2;
1904
1905 str1 = _PyUnicode_FromId(&PyId_test_unicode_id_init);
1906 assert(str1 != NULL);
1907 assert(Py_REFCNT(str1) == 1);
1908
1909 str2 = PyUnicode_FromString("test_unicode_id_init");
1910 assert(str2 != NULL);
1911
1912 assert(PyUnicode_Compare(str1, str2) == 0);
1913
1914 // str1 is a borrowed reference
1915 Py_DECREF(str2);
1916
1917 Py_Finalize();
1918 }
1919 return 0;
1920 }
1921
1922
1923 #ifndef MS_WINDOWS
1924 #include "test_frozenmain.h" // M_test_frozenmain
1925
test_frozenmain(void)1926 static int test_frozenmain(void)
1927 {
1928 static struct _frozen frozen_modules[4] = {
1929 {"__main__", M_test_frozenmain, sizeof(M_test_frozenmain)},
1930 {0, 0, 0} // sentinel
1931 };
1932
1933 char* argv[] = {
1934 "./argv0",
1935 "-E",
1936 "arg1",
1937 "arg2",
1938 };
1939 PyImport_FrozenModules = frozen_modules;
1940 return Py_FrozenMain(Py_ARRAY_LENGTH(argv), argv);
1941 }
1942 #endif // !MS_WINDOWS
1943
test_repeated_init_and_inittab(void)1944 static int test_repeated_init_and_inittab(void)
1945 {
1946 // bpo-44441: Py_RunMain() must reset PyImport_Inittab at exit.
1947 // It must be possible to call PyImport_AppendInittab() or
1948 // PyImport_ExtendInittab() before each Python initialization.
1949 for (int i=1; i <= INIT_LOOPS; i++) {
1950 printf("--- Pass %d ---\n", i);
1951
1952 // Call PyImport_AppendInittab() at each iteration
1953 if (PyImport_AppendInittab(EMBEDDED_EXT_NAME,
1954 &PyInit_embedded_ext) != 0) {
1955 fprintf(stderr, "PyImport_AppendInittab() failed\n");
1956 return 1;
1957 }
1958
1959 // Initialize Python
1960 wchar_t* argv[] = {PROGRAM_NAME, L"-c", L"pass"};
1961 PyConfig config;
1962 PyConfig_InitPythonConfig(&config);
1963 config.isolated = 1;
1964 config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
1965 init_from_config_clear(&config);
1966
1967 // Py_RunMain() calls _PyImport_Fini2() which resets PyImport_Inittab
1968 int exitcode = Py_RunMain();
1969 if (exitcode != 0) {
1970 return exitcode;
1971 }
1972 }
1973 return 0;
1974 }
1975
1976 static void wrap_allocator(PyMemAllocatorEx *allocator);
1977 static void unwrap_allocator(PyMemAllocatorEx *allocator);
1978
1979 static void *
malloc_wrapper(void * ctx,size_t size)1980 malloc_wrapper(void *ctx, size_t size)
1981 {
1982 PyMemAllocatorEx *allocator = (PyMemAllocatorEx *)ctx;
1983 unwrap_allocator(allocator);
1984 PyEval_GetFrame(); // BOOM!
1985 wrap_allocator(allocator);
1986 return allocator->malloc(allocator->ctx, size);
1987 }
1988
1989 static void *
calloc_wrapper(void * ctx,size_t nelem,size_t elsize)1990 calloc_wrapper(void *ctx, size_t nelem, size_t elsize)
1991 {
1992 PyMemAllocatorEx *allocator = (PyMemAllocatorEx *)ctx;
1993 return allocator->calloc(allocator->ctx, nelem, elsize);
1994 }
1995
1996 static void *
realloc_wrapper(void * ctx,void * ptr,size_t new_size)1997 realloc_wrapper(void *ctx, void *ptr, size_t new_size)
1998 {
1999 PyMemAllocatorEx *allocator = (PyMemAllocatorEx *)ctx;
2000 return allocator->realloc(allocator->ctx, ptr, new_size);
2001 }
2002
2003 static void
free_wrapper(void * ctx,void * ptr)2004 free_wrapper(void *ctx, void *ptr)
2005 {
2006 PyMemAllocatorEx *allocator = (PyMemAllocatorEx *)ctx;
2007 allocator->free(allocator->ctx, ptr);
2008 }
2009
2010 static void
wrap_allocator(PyMemAllocatorEx * allocator)2011 wrap_allocator(PyMemAllocatorEx *allocator)
2012 {
2013 PyMem_GetAllocator(PYMEM_DOMAIN_OBJ, allocator);
2014 PyMemAllocatorEx wrapper = {
2015 .malloc = &malloc_wrapper,
2016 .calloc = &calloc_wrapper,
2017 .realloc = &realloc_wrapper,
2018 .free = &free_wrapper,
2019 .ctx = allocator,
2020 };
2021 PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &wrapper);
2022 }
2023
2024 static void
unwrap_allocator(PyMemAllocatorEx * allocator)2025 unwrap_allocator(PyMemAllocatorEx *allocator)
2026 {
2027 PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, allocator);
2028 }
2029
2030 static int
test_get_incomplete_frame(void)2031 test_get_incomplete_frame(void)
2032 {
2033 _testembed_Py_InitializeFromConfig();
2034 PyMemAllocatorEx allocator;
2035 wrap_allocator(&allocator);
2036 // Force an allocation with an incomplete (generator) frame:
2037 int result = PyRun_SimpleString("(_ for _ in ())");
2038 unwrap_allocator(&allocator);
2039 Py_Finalize();
2040 return result;
2041 }
2042
2043
2044 /* *********************************************************
2045 * List of test cases and the function that implements it.
2046 *
2047 * Names are compared case-sensitively with the first
2048 * argument. If no match is found, or no first argument was
2049 * provided, the names of all test cases are printed and
2050 * the exit code will be -1.
2051 *
2052 * The int returned from test functions is used as the exit
2053 * code, and test_capi treats all non-zero exit codes as a
2054 * failed test.
2055 *********************************************************/
2056 struct TestCase
2057 {
2058 const char *name;
2059 int (*func)(void);
2060 };
2061
2062 static struct TestCase TestCases[] = {
2063 // Python initialization
2064 {"test_repeated_init_exec", test_repeated_init_exec},
2065 {"test_repeated_simple_init", test_repeated_simple_init},
2066 {"test_forced_io_encoding", test_forced_io_encoding},
2067 {"test_repeated_init_and_subinterpreters", test_repeated_init_and_subinterpreters},
2068 {"test_repeated_init_and_inittab", test_repeated_init_and_inittab},
2069 {"test_pre_initialization_api", test_pre_initialization_api},
2070 {"test_pre_initialization_sys_options", test_pre_initialization_sys_options},
2071 {"test_bpo20891", test_bpo20891},
2072 {"test_initialize_twice", test_initialize_twice},
2073 {"test_initialize_pymain", test_initialize_pymain},
2074 {"test_init_initialize_config", test_init_initialize_config},
2075 {"test_preinit_compat_config", test_preinit_compat_config},
2076 {"test_init_compat_config", test_init_compat_config},
2077 {"test_init_global_config", test_init_global_config},
2078 {"test_init_from_config", test_init_from_config},
2079 {"test_init_parse_argv", test_init_parse_argv},
2080 {"test_init_dont_parse_argv", test_init_dont_parse_argv},
2081 {"test_init_compat_env", test_init_compat_env},
2082 {"test_init_python_env", test_init_python_env},
2083 {"test_init_env_dev_mode", test_init_env_dev_mode},
2084 {"test_init_env_dev_mode_alloc", test_init_env_dev_mode_alloc},
2085 {"test_init_dont_configure_locale", test_init_dont_configure_locale},
2086 {"test_init_dev_mode", test_init_dev_mode},
2087 {"test_init_isolated_flag", test_init_isolated_flag},
2088 {"test_preinit_isolated_config", test_preinit_isolated_config},
2089 {"test_init_isolated_config", test_init_isolated_config},
2090 {"test_preinit_python_config", test_preinit_python_config},
2091 {"test_init_python_config", test_init_python_config},
2092 {"test_preinit_isolated1", test_preinit_isolated1},
2093 {"test_preinit_isolated2", test_preinit_isolated2},
2094 {"test_preinit_parse_argv", test_preinit_parse_argv},
2095 {"test_preinit_dont_parse_argv", test_preinit_dont_parse_argv},
2096 {"test_init_read_set", test_init_read_set},
2097 {"test_init_run_main", test_init_run_main},
2098 {"test_init_main", test_init_main},
2099 {"test_init_sys_add", test_init_sys_add},
2100 {"test_init_setpath", test_init_setpath},
2101 {"test_init_setpath_config", test_init_setpath_config},
2102 {"test_init_setpythonhome", test_init_setpythonhome},
2103 {"test_init_is_python_build", test_init_is_python_build},
2104 {"test_init_warnoptions", test_init_warnoptions},
2105 {"test_init_set_config", test_init_set_config},
2106 {"test_run_main", test_run_main},
2107 {"test_run_main_loop", test_run_main_loop},
2108 {"test_get_argc_argv", test_get_argc_argv},
2109 {"test_init_use_frozen_modules", test_init_use_frozen_modules},
2110
2111 // Audit
2112 {"test_open_code_hook", test_open_code_hook},
2113 {"test_audit", test_audit},
2114 {"test_audit_subinterpreter", test_audit_subinterpreter},
2115 {"test_audit_run_command", test_audit_run_command},
2116 {"test_audit_run_file", test_audit_run_file},
2117 {"test_audit_run_interactivehook", test_audit_run_interactivehook},
2118 {"test_audit_run_startup", test_audit_run_startup},
2119 {"test_audit_run_stdin", test_audit_run_stdin},
2120
2121 // Specific C API
2122 {"test_unicode_id_init", test_unicode_id_init},
2123 #ifndef MS_WINDOWS
2124 {"test_frozenmain", test_frozenmain},
2125 #endif
2126 {"test_get_incomplete_frame", test_get_incomplete_frame},
2127
2128 {NULL, NULL}
2129 };
2130
2131
main(int argc,char * argv[])2132 int main(int argc, char *argv[])
2133 {
2134 main_argc = argc;
2135 main_argv = argv;
2136
2137 if (argc > 1) {
2138 for (struct TestCase *tc = TestCases; tc && tc->name; tc++) {
2139 if (strcmp(argv[1], tc->name) == 0)
2140 return (*tc->func)();
2141 }
2142 }
2143
2144 /* No match found, or no test name provided, so display usage */
2145 printf("Python " PY_VERSION " _testembed executable for embedded interpreter tests\n"
2146 "Normally executed via 'EmbeddingTests' in Lib/test/test_embed.py\n\n"
2147 "Usage: %s TESTNAME\n\nAll available tests:\n", argv[0]);
2148 for (struct TestCase *tc = TestCases; tc && tc->name; tc++) {
2149 printf(" %s\n", tc->name);
2150 }
2151
2152 /* Non-zero exit code will cause test_embed.py tests to fail.
2153 This is intentional. */
2154 return -1;
2155 }
2156