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 19int main_argc; 20char **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 42static void error(const char *msg) 43{ 44 fprintf(stderr, "ERROR: %s\n", msg); 45 fflush(stderr); 46} 47 48 49static 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 59static 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 66static 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 76static 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 84static 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 95static 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 112static 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 146static PyModuleDef embedded_ext = { 147 PyModuleDef_HEAD_INIT, 148 .m_name = EMBEDDED_EXT_NAME, 149 .m_size = 0, 150}; 151 152static PyObject* 153PyInit_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. 165static 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) 191static 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 209static 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 236static 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 268static 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 */ 298static 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 */ 350static 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 365static 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 399static 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 412static 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 430static void 431dump_config(void) 432{ 433 (void) PyRun_SimpleStringFlags( 434 "import _testinternalcapi, json; " 435 "print(json.dumps(_testinternalcapi.get_configs()))", 436 0); 437} 438 439 440static int test_init_initialize_config(void) 441{ 442 _testembed_Py_InitializeFromConfig(); 443 dump_config(); 444 Py_Finalize(); 445 return 0; 446} 447 448 449static 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 459static void 460config_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 471static 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 497static int test_preinit_compat_config(void) 498{ 499 return check_init_compat_config(1); 500} 501 502 503static int test_init_compat_config(void) 504{ 505 return check_init_compat_config(0); 506} 507 508 509static 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 558static 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 717static 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 742static int test_init_parse_argv(void) 743{ 744 return check_init_parse_argv(1); 745} 746 747 748static int test_init_dont_parse_argv(void) 749{ 750 return check_init_parse_argv(0); 751} 752 753 754static 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 777static 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 786static 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 798static 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 814static void set_all_env_vars_dev_mode(void) 815{ 816 putenv("PYTHONMALLOC="); 817 putenv("PYTHONFAULTHANDLER="); 818 putenv("PYTHONDEVMODE=1"); 819} 820 821 822static 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 834static 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 847static 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 */ 871static 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 */ 897static 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 926static 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 964static 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 984static 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 1006static 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 1047static int test_preinit_isolated_config(void) 1048{ 1049 return check_preinit_isolated_config(1); 1050} 1051 1052 1053static int test_init_isolated_config(void) 1054{ 1055 return check_preinit_isolated_config(0); 1056} 1057 1058 1059static 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 1096static int test_preinit_python_config(void) 1097{ 1098 return check_init_python_config(1); 1099} 1100 1101 1102static int test_init_python_config(void) 1103{ 1104 return check_init_python_config(0); 1105} 1106 1107 1108static 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 1134static 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 1150static 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 1162static 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 1219static int _audit_hook_clear_count = 0; 1220 1221static 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 1238static 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 1275static 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 1285static volatile int _audit_subinterpreter_interpreter_count = 0; 1286 1287static 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 1296static 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 1315typedef struct { 1316 const char* expected; 1317 int exit; 1318} AuditRunCommandTest; 1319 1320static 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 1340static 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 1351static 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 1362static 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 1386static 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 1393static 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 1400static 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 1407static 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 1444fail: 1445 PyConfig_Clear(&config); 1446 Py_ExitStatusException(status); 1447} 1448 1449 1450static 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 1489fail: 1490 PyConfig_Clear(&config); 1491 Py_ExitStatusException(status); 1492} 1493 1494 1495static 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 1518static 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 1557static 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 1580static 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 1620static 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 1673static 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 1694static 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 1722static 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 1737static 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 1749static 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 1776static 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 1793static 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 1807static 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 1844static 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 1881static int test_init_use_frozen_modules(void) 1882{ 1883 const char *envvar = getenv("TESTFROZEN"); 1884 return check_use_frozen_modules(envvar); 1885} 1886 1887 1888static 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 1926static 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 1944static 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 1976static void wrap_allocator(PyMemAllocatorEx *allocator); 1977static void unwrap_allocator(PyMemAllocatorEx *allocator); 1978 1979static void * 1980malloc_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 1989static void * 1990calloc_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 1996static void * 1997realloc_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 2003static void 2004free_wrapper(void *ctx, void *ptr) 2005{ 2006 PyMemAllocatorEx *allocator = (PyMemAllocatorEx *)ctx; 2007 allocator->free(allocator->ctx, ptr); 2008} 2009 2010static void 2011wrap_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 2024static void 2025unwrap_allocator(PyMemAllocatorEx *allocator) 2026{ 2027 PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, allocator); 2028} 2029 2030static int 2031test_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 *********************************************************/ 2056struct TestCase 2057{ 2058 const char *name; 2059 int (*func)(void); 2060}; 2061 2062static 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 2132int 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