You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

907 lines
24 KiB

  1. /* FIXME: PEP 587 makes these functions public */
  2. #ifndef Py_BUILD_CORE_MODULE
  3. # define Py_BUILD_CORE_MODULE
  4. #endif
  5. #include <Python.h>
  6. #include "pycore_coreconfig.h" /* FIXME: PEP 587 makes these functions public */
  7. #include "pythread.h"
  8. #include <inttypes.h>
  9. #include <stdio.h>
  10. #include <wchar.h>
  11. /*********************************************************
  12. * Embedded interpreter tests that need a custom exe
  13. *
  14. * Executed via 'EmbeddingTests' in Lib/test/test_capi.py
  15. *********************************************************/
  16. static void _testembed_Py_Initialize(void)
  17. {
  18. /* HACK: the "./" at front avoids a search along the PATH in
  19. Modules/getpath.c */
  20. Py_SetProgramName(L"./_testembed");
  21. Py_Initialize();
  22. }
  23. /*****************************************************
  24. * Test repeated initialisation and subinterpreters
  25. *****************************************************/
  26. static void print_subinterp(void)
  27. {
  28. /* Output information about the interpreter in the format
  29. expected in Lib/test/test_capi.py (test_subinterps). */
  30. PyThreadState *ts = PyThreadState_Get();
  31. PyInterpreterState *interp = ts->interp;
  32. int64_t id = PyInterpreterState_GetID(interp);
  33. printf("interp %" PRId64 " <0x%" PRIXPTR ">, thread state <0x%" PRIXPTR ">: ",
  34. id, (uintptr_t)interp, (uintptr_t)ts);
  35. fflush(stdout);
  36. PyRun_SimpleString(
  37. "import sys;"
  38. "print('id(modules) =', id(sys.modules));"
  39. "sys.stdout.flush()"
  40. );
  41. }
  42. static int test_repeated_init_and_subinterpreters(void)
  43. {
  44. PyThreadState *mainstate, *substate;
  45. PyGILState_STATE gilstate;
  46. int i, j;
  47. for (i=0; i<15; i++) {
  48. printf("--- Pass %d ---\n", i);
  49. _testembed_Py_Initialize();
  50. mainstate = PyThreadState_Get();
  51. PyEval_InitThreads();
  52. PyEval_ReleaseThread(mainstate);
  53. gilstate = PyGILState_Ensure();
  54. print_subinterp();
  55. PyThreadState_Swap(NULL);
  56. for (j=0; j<3; j++) {
  57. substate = Py_NewInterpreter();
  58. print_subinterp();
  59. Py_EndInterpreter(substate);
  60. }
  61. PyThreadState_Swap(mainstate);
  62. print_subinterp();
  63. PyGILState_Release(gilstate);
  64. PyEval_RestoreThread(mainstate);
  65. Py_Finalize();
  66. }
  67. return 0;
  68. }
  69. /*****************************************************
  70. * Test forcing a particular IO encoding
  71. *****************************************************/
  72. static void check_stdio_details(const char *encoding, const char * errors)
  73. {
  74. /* Output info for the test case to check */
  75. if (encoding) {
  76. printf("Expected encoding: %s\n", encoding);
  77. } else {
  78. printf("Expected encoding: default\n");
  79. }
  80. if (errors) {
  81. printf("Expected errors: %s\n", errors);
  82. } else {
  83. printf("Expected errors: default\n");
  84. }
  85. fflush(stdout);
  86. /* Force the given IO encoding */
  87. Py_SetStandardStreamEncoding(encoding, errors);
  88. _testembed_Py_Initialize();
  89. PyRun_SimpleString(
  90. "import sys;"
  91. "print('stdin: {0.encoding}:{0.errors}'.format(sys.stdin));"
  92. "print('stdout: {0.encoding}:{0.errors}'.format(sys.stdout));"
  93. "print('stderr: {0.encoding}:{0.errors}'.format(sys.stderr));"
  94. "sys.stdout.flush()"
  95. );
  96. Py_Finalize();
  97. }
  98. static int test_forced_io_encoding(void)
  99. {
  100. /* Check various combinations */
  101. printf("--- Use defaults ---\n");
  102. check_stdio_details(NULL, NULL);
  103. printf("--- Set errors only ---\n");
  104. check_stdio_details(NULL, "ignore");
  105. printf("--- Set encoding only ---\n");
  106. check_stdio_details("iso8859-1", NULL);
  107. printf("--- Set encoding and errors ---\n");
  108. check_stdio_details("iso8859-1", "replace");
  109. /* Check calling after initialization fails */
  110. Py_Initialize();
  111. if (Py_SetStandardStreamEncoding(NULL, NULL) == 0) {
  112. printf("Unexpected success calling Py_SetStandardStreamEncoding");
  113. }
  114. Py_Finalize();
  115. return 0;
  116. }
  117. /*********************************************************
  118. * Test parts of the C-API that work before initialization
  119. *********************************************************/
  120. /* The pre-initialization tests tend to break by segfaulting, so explicitly
  121. * flushed progress messages make the broken API easier to find when they fail.
  122. */
  123. #define _Py_EMBED_PREINIT_CHECK(msg) \
  124. do {printf(msg); fflush(stdout);} while (0);
  125. static int test_pre_initialization_api(void)
  126. {
  127. /* the test doesn't support custom memory allocators */
  128. putenv("PYTHONMALLOC=");
  129. /* Leading "./" ensures getpath.c can still find the standard library */
  130. _Py_EMBED_PREINIT_CHECK("Checking Py_DecodeLocale\n");
  131. wchar_t *program = Py_DecodeLocale("./spam", NULL);
  132. if (program == NULL) {
  133. fprintf(stderr, "Fatal error: cannot decode program name\n");
  134. return 1;
  135. }
  136. _Py_EMBED_PREINIT_CHECK("Checking Py_SetProgramName\n");
  137. Py_SetProgramName(program);
  138. _Py_EMBED_PREINIT_CHECK("Initializing interpreter\n");
  139. Py_Initialize();
  140. _Py_EMBED_PREINIT_CHECK("Check sys module contents\n");
  141. PyRun_SimpleString("import sys; "
  142. "print('sys.executable:', sys.executable)");
  143. _Py_EMBED_PREINIT_CHECK("Finalizing interpreter\n");
  144. Py_Finalize();
  145. _Py_EMBED_PREINIT_CHECK("Freeing memory allocated by Py_DecodeLocale\n");
  146. PyMem_RawFree(program);
  147. return 0;
  148. }
  149. /* bpo-33042: Ensure embedding apps can predefine sys module options */
  150. static int test_pre_initialization_sys_options(void)
  151. {
  152. /* We allocate a couple of the options dynamically, and then delete
  153. * them before calling Py_Initialize. This ensures the interpreter isn't
  154. * relying on the caller to keep the passed in strings alive.
  155. */
  156. const wchar_t *static_warnoption = L"once";
  157. const wchar_t *static_xoption = L"also_not_an_option=2";
  158. size_t warnoption_len = wcslen(static_warnoption);
  159. size_t xoption_len = wcslen(static_xoption);
  160. wchar_t *dynamic_once_warnoption = \
  161. (wchar_t *) calloc(warnoption_len+1, sizeof(wchar_t));
  162. wchar_t *dynamic_xoption = \
  163. (wchar_t *) calloc(xoption_len+1, sizeof(wchar_t));
  164. wcsncpy(dynamic_once_warnoption, static_warnoption, warnoption_len+1);
  165. wcsncpy(dynamic_xoption, static_xoption, xoption_len+1);
  166. _Py_EMBED_PREINIT_CHECK("Checking PySys_AddWarnOption\n");
  167. PySys_AddWarnOption(L"default");
  168. _Py_EMBED_PREINIT_CHECK("Checking PySys_ResetWarnOptions\n");
  169. PySys_ResetWarnOptions();
  170. _Py_EMBED_PREINIT_CHECK("Checking PySys_AddWarnOption linked list\n");
  171. PySys_AddWarnOption(dynamic_once_warnoption);
  172. PySys_AddWarnOption(L"module");
  173. PySys_AddWarnOption(L"default");
  174. _Py_EMBED_PREINIT_CHECK("Checking PySys_AddXOption\n");
  175. PySys_AddXOption(L"not_an_option=1");
  176. PySys_AddXOption(dynamic_xoption);
  177. /* Delete the dynamic options early */
  178. free(dynamic_once_warnoption);
  179. dynamic_once_warnoption = NULL;
  180. free(dynamic_xoption);
  181. dynamic_xoption = NULL;
  182. _Py_EMBED_PREINIT_CHECK("Initializing interpreter\n");
  183. _testembed_Py_Initialize();
  184. _Py_EMBED_PREINIT_CHECK("Check sys module contents\n");
  185. PyRun_SimpleString("import sys; "
  186. "print('sys.warnoptions:', sys.warnoptions); "
  187. "print('sys._xoptions:', sys._xoptions); "
  188. "warnings = sys.modules['warnings']; "
  189. "latest_filters = [f[0] for f in warnings.filters[:3]]; "
  190. "print('warnings.filters[:3]:', latest_filters)");
  191. _Py_EMBED_PREINIT_CHECK("Finalizing interpreter\n");
  192. Py_Finalize();
  193. return 0;
  194. }
  195. /* bpo-20891: Avoid race condition when initialising the GIL */
  196. static void bpo20891_thread(void *lockp)
  197. {
  198. PyThread_type_lock lock = *((PyThread_type_lock*)lockp);
  199. PyGILState_STATE state = PyGILState_Ensure();
  200. if (!PyGILState_Check()) {
  201. fprintf(stderr, "PyGILState_Check failed!");
  202. abort();
  203. }
  204. PyGILState_Release(state);
  205. PyThread_release_lock(lock);
  206. PyThread_exit_thread();
  207. }
  208. static int test_bpo20891(void)
  209. {
  210. /* the test doesn't support custom memory allocators */
  211. putenv("PYTHONMALLOC=");
  212. /* bpo-20891: Calling PyGILState_Ensure in a non-Python thread before
  213. calling PyEval_InitThreads() must not crash. PyGILState_Ensure() must
  214. call PyEval_InitThreads() for us in this case. */
  215. PyThread_type_lock lock = PyThread_allocate_lock();
  216. if (!lock) {
  217. fprintf(stderr, "PyThread_allocate_lock failed!");
  218. return 1;
  219. }
  220. _testembed_Py_Initialize();
  221. unsigned long thrd = PyThread_start_new_thread(bpo20891_thread, &lock);
  222. if (thrd == PYTHREAD_INVALID_THREAD_ID) {
  223. fprintf(stderr, "PyThread_start_new_thread failed!");
  224. return 1;
  225. }
  226. PyThread_acquire_lock(lock, WAIT_LOCK);
  227. Py_BEGIN_ALLOW_THREADS
  228. /* wait until the thread exit */
  229. PyThread_acquire_lock(lock, WAIT_LOCK);
  230. Py_END_ALLOW_THREADS
  231. PyThread_free_lock(lock);
  232. return 0;
  233. }
  234. static int test_initialize_twice(void)
  235. {
  236. _testembed_Py_Initialize();
  237. /* bpo-33932: Calling Py_Initialize() twice should do nothing
  238. * (and not crash!). */
  239. Py_Initialize();
  240. Py_Finalize();
  241. return 0;
  242. }
  243. static int test_initialize_pymain(void)
  244. {
  245. wchar_t *argv[] = {L"PYTHON", L"-c",
  246. L"import sys; print(f'Py_Main() after Py_Initialize: sys.argv={sys.argv}')",
  247. L"arg2"};
  248. _testembed_Py_Initialize();
  249. /* bpo-34008: Calling Py_Main() after Py_Initialize() must not crash */
  250. Py_Main(Py_ARRAY_LENGTH(argv), argv);
  251. Py_Finalize();
  252. return 0;
  253. }
  254. static void
  255. dump_config(void)
  256. {
  257. (void) PyRun_SimpleStringFlags(
  258. "import _testinternalcapi, json; "
  259. "print(json.dumps(_testinternalcapi.get_configs()))",
  260. 0);
  261. }
  262. static int test_init_default_config(void)
  263. {
  264. _testembed_Py_Initialize();
  265. dump_config();
  266. Py_Finalize();
  267. return 0;
  268. }
  269. static int test_init_global_config(void)
  270. {
  271. /* FIXME: test Py_IgnoreEnvironmentFlag */
  272. putenv("PYTHONUTF8=0");
  273. Py_UTF8Mode = 1;
  274. /* Test initialization from global configuration variables (Py_xxx) */
  275. Py_SetProgramName(L"./globalvar");
  276. /* Py_IsolatedFlag is not tested */
  277. Py_NoSiteFlag = 1;
  278. Py_BytesWarningFlag = 1;
  279. putenv("PYTHONINSPECT=");
  280. Py_InspectFlag = 1;
  281. putenv("PYTHONOPTIMIZE=0");
  282. Py_InteractiveFlag = 1;
  283. putenv("PYTHONDEBUG=0");
  284. Py_OptimizeFlag = 2;
  285. /* Py_DebugFlag is not tested */
  286. putenv("PYTHONDONTWRITEBYTECODE=");
  287. Py_DontWriteBytecodeFlag = 1;
  288. putenv("PYTHONVERBOSE=0");
  289. Py_VerboseFlag = 1;
  290. Py_QuietFlag = 1;
  291. Py_NoUserSiteDirectory = 1;
  292. putenv("PYTHONUNBUFFERED=");
  293. Py_UnbufferedStdioFlag = 1;
  294. Py_FrozenFlag = 1;
  295. /* FIXME: test Py_LegacyWindowsFSEncodingFlag */
  296. /* FIXME: test Py_LegacyWindowsStdioFlag */
  297. Py_Initialize();
  298. dump_config();
  299. Py_Finalize();
  300. return 0;
  301. }
  302. static int test_init_from_config(void)
  303. {
  304. _PyInitError err;
  305. _PyPreConfig preconfig = _PyPreConfig_INIT;
  306. putenv("PYTHONMALLOC=malloc_debug");
  307. preconfig.allocator = PYMEM_ALLOCATOR_MALLOC;
  308. putenv("PYTHONUTF8=0");
  309. Py_UTF8Mode = 0;
  310. preconfig.utf8_mode = 1;
  311. err = _Py_PreInitialize(&preconfig);
  312. if (_Py_INIT_FAILED(err)) {
  313. _Py_ExitInitError(err);
  314. }
  315. /* Test _Py_InitializeFromConfig() */
  316. _PyCoreConfig config = _PyCoreConfig_INIT;
  317. config.install_signal_handlers = 0;
  318. /* FIXME: test use_environment */
  319. putenv("PYTHONHASHSEED=42");
  320. config.use_hash_seed = 1;
  321. config.hash_seed = 123;
  322. /* dev_mode=1 is tested in test_init_dev_mode() */
  323. putenv("PYTHONFAULTHANDLER=");
  324. config.faulthandler = 1;
  325. putenv("PYTHONTRACEMALLOC=0");
  326. config.tracemalloc = 2;
  327. putenv("PYTHONPROFILEIMPORTTIME=0");
  328. config.import_time = 1;
  329. config.show_ref_count = 1;
  330. config.show_alloc_count = 1;
  331. /* FIXME: test dump_refs: bpo-34223 */
  332. putenv("PYTHONMALLOCSTATS=0");
  333. config.malloc_stats = 1;
  334. putenv("PYTHONPYCACHEPREFIX=env_pycache_prefix");
  335. config.pycache_prefix = L"conf_pycache_prefix";
  336. Py_SetProgramName(L"./globalvar");
  337. config.program_name = L"./conf_program_name";
  338. static wchar_t* argv[] = {
  339. L"python3",
  340. L"-c",
  341. L"pass",
  342. L"arg2",
  343. };
  344. config.argv.length = Py_ARRAY_LENGTH(argv);
  345. config.argv.items = argv;
  346. static wchar_t* xoptions[3] = {
  347. L"core_xoption1=3",
  348. L"core_xoption2=",
  349. L"core_xoption3",
  350. };
  351. config.xoptions.length = Py_ARRAY_LENGTH(xoptions);
  352. config.xoptions.items = xoptions;
  353. static wchar_t* warnoptions[1] = {
  354. L"error::ResourceWarning",
  355. };
  356. config.warnoptions.length = Py_ARRAY_LENGTH(warnoptions);
  357. config.warnoptions.items = warnoptions;
  358. /* FIXME: test module_search_path_env */
  359. /* FIXME: test home */
  360. /* FIXME: test path config: module_search_path .. dll_path */
  361. putenv("PYTHONVERBOSE=0");
  362. Py_VerboseFlag = 0;
  363. config.verbose = 1;
  364. Py_NoSiteFlag = 0;
  365. config.site_import = 0;
  366. Py_BytesWarningFlag = 0;
  367. config.bytes_warning = 1;
  368. putenv("PYTHONINSPECT=");
  369. Py_InspectFlag = 0;
  370. config.inspect = 1;
  371. Py_InteractiveFlag = 0;
  372. config.interactive = 1;
  373. putenv("PYTHONOPTIMIZE=0");
  374. Py_OptimizeFlag = 1;
  375. config.optimization_level = 2;
  376. /* FIXME: test parser_debug */
  377. putenv("PYTHONDONTWRITEBYTECODE=");
  378. Py_DontWriteBytecodeFlag = 0;
  379. config.write_bytecode = 0;
  380. Py_QuietFlag = 0;
  381. config.quiet = 1;
  382. config.configure_c_stdio = 0;
  383. putenv("PYTHONUNBUFFERED=");
  384. Py_UnbufferedStdioFlag = 0;
  385. config.buffered_stdio = 0;
  386. putenv("PYTHONIOENCODING=cp424");
  387. Py_SetStandardStreamEncoding("ascii", "ignore");
  388. #ifdef MS_WINDOWS
  389. /* Py_SetStandardStreamEncoding() sets Py_LegacyWindowsStdioFlag to 1.
  390. Force it to 0 through the config. */
  391. config.legacy_windows_stdio = 0;
  392. #endif
  393. config.stdio_encoding = L"iso8859-1";
  394. config.stdio_errors = L"replace";
  395. putenv("PYTHONNOUSERSITE=");
  396. Py_NoUserSiteDirectory = 0;
  397. config.user_site_directory = 0;
  398. config.check_hash_pycs_mode = L"always";
  399. Py_FrozenFlag = 0;
  400. config.pathconfig_warnings = 0;
  401. err = _Py_InitializeFromConfig(&config);
  402. if (_Py_INIT_FAILED(err)) {
  403. _Py_ExitInitError(err);
  404. }
  405. dump_config();
  406. Py_Finalize();
  407. return 0;
  408. }
  409. static int test_init_dont_parse_argv(void)
  410. {
  411. _PyInitError err;
  412. _PyCoreConfig config = _PyCoreConfig_INIT;
  413. static wchar_t* argv[] = {
  414. L"-v",
  415. L"-c",
  416. L"arg1",
  417. L"-W",
  418. L"arg2",
  419. };
  420. config.program_name = L"./_testembed";
  421. config.argv.length = Py_ARRAY_LENGTH(argv);
  422. config.argv.items = argv;
  423. config.parse_argv = 0;
  424. err = _Py_InitializeFromConfig(&config);
  425. if (_Py_INIT_FAILED(err)) {
  426. _Py_ExitInitError(err);
  427. }
  428. dump_config();
  429. Py_Finalize();
  430. return 0;
  431. }
  432. static void test_init_env_putenvs(void)
  433. {
  434. putenv("PYTHONHASHSEED=42");
  435. putenv("PYTHONMALLOC=malloc");
  436. putenv("PYTHONTRACEMALLOC=2");
  437. putenv("PYTHONPROFILEIMPORTTIME=1");
  438. putenv("PYTHONMALLOCSTATS=1");
  439. putenv("PYTHONUTF8=1");
  440. putenv("PYTHONVERBOSE=1");
  441. putenv("PYTHONINSPECT=1");
  442. putenv("PYTHONOPTIMIZE=2");
  443. putenv("PYTHONDONTWRITEBYTECODE=1");
  444. putenv("PYTHONUNBUFFERED=1");
  445. putenv("PYTHONPYCACHEPREFIX=env_pycache_prefix");
  446. putenv("PYTHONNOUSERSITE=1");
  447. putenv("PYTHONFAULTHANDLER=1");
  448. putenv("PYTHONIOENCODING=iso8859-1:replace");
  449. /* FIXME: test PYTHONWARNINGS */
  450. /* FIXME: test PYTHONEXECUTABLE */
  451. /* FIXME: test PYTHONHOME */
  452. /* FIXME: test PYTHONDEBUG */
  453. /* FIXME: test PYTHONDUMPREFS */
  454. /* FIXME: test PYTHONCOERCECLOCALE */
  455. /* FIXME: test PYTHONPATH */
  456. }
  457. static int test_init_env(void)
  458. {
  459. /* Test initialization from environment variables */
  460. Py_IgnoreEnvironmentFlag = 0;
  461. test_init_env_putenvs();
  462. _testembed_Py_Initialize();
  463. dump_config();
  464. Py_Finalize();
  465. return 0;
  466. }
  467. static void test_init_env_dev_mode_putenvs(void)
  468. {
  469. test_init_env_putenvs();
  470. putenv("PYTHONMALLOC=");
  471. putenv("PYTHONFAULTHANDLER=");
  472. putenv("PYTHONDEVMODE=1");
  473. }
  474. static int test_init_env_dev_mode(void)
  475. {
  476. /* Test initialization from environment variables */
  477. Py_IgnoreEnvironmentFlag = 0;
  478. test_init_env_dev_mode_putenvs();
  479. _testembed_Py_Initialize();
  480. dump_config();
  481. Py_Finalize();
  482. return 0;
  483. }
  484. static int test_init_env_dev_mode_alloc(void)
  485. {
  486. /* Test initialization from environment variables */
  487. Py_IgnoreEnvironmentFlag = 0;
  488. test_init_env_dev_mode_putenvs();
  489. putenv("PYTHONMALLOC=malloc");
  490. _testembed_Py_Initialize();
  491. dump_config();
  492. Py_Finalize();
  493. return 0;
  494. }
  495. static int test_init_isolated(void)
  496. {
  497. _PyInitError err;
  498. /* Test _PyCoreConfig.isolated=1 */
  499. _PyCoreConfig config = _PyCoreConfig_INIT;
  500. Py_IsolatedFlag = 0;
  501. config.isolated = 1;
  502. /* Use path starting with "./" avoids a search along the PATH */
  503. config.program_name = L"./_testembed";
  504. test_init_env_dev_mode_putenvs();
  505. err = _Py_InitializeFromConfig(&config);
  506. if (_Py_INIT_FAILED(err)) {
  507. _Py_ExitInitError(err);
  508. }
  509. dump_config();
  510. Py_Finalize();
  511. return 0;
  512. }
  513. /* _PyPreConfig.isolated=1, _PyCoreConfig.isolated=0 */
  514. static int test_preinit_isolated1(void)
  515. {
  516. _PyInitError err;
  517. _PyPreConfig preconfig = _PyPreConfig_INIT;
  518. preconfig.isolated = 1;
  519. err = _Py_PreInitialize(&preconfig);
  520. if (_Py_INIT_FAILED(err)) {
  521. _Py_ExitInitError(err);
  522. }
  523. _PyCoreConfig config = _PyCoreConfig_INIT;
  524. config.program_name = L"./_testembed";
  525. test_init_env_dev_mode_putenvs();
  526. err = _Py_InitializeFromConfig(&config);
  527. if (_Py_INIT_FAILED(err)) {
  528. _Py_ExitInitError(err);
  529. }
  530. dump_config();
  531. Py_Finalize();
  532. return 0;
  533. }
  534. /* _PyPreConfig.isolated=0, _PyCoreConfig.isolated=1 */
  535. static int test_preinit_isolated2(void)
  536. {
  537. _PyInitError err;
  538. _PyPreConfig preconfig = _PyPreConfig_INIT;
  539. preconfig.isolated = 0;
  540. err = _Py_PreInitialize(&preconfig);
  541. if (_Py_INIT_FAILED(err)) {
  542. _Py_ExitInitError(err);
  543. }
  544. /* Test _PyCoreConfig.isolated=1 */
  545. _PyCoreConfig config = _PyCoreConfig_INIT;
  546. Py_IsolatedFlag = 0;
  547. config.isolated = 1;
  548. /* Use path starting with "./" avoids a search along the PATH */
  549. config.program_name = L"./_testembed";
  550. test_init_env_dev_mode_putenvs();
  551. err = _Py_InitializeFromConfig(&config);
  552. if (_Py_INIT_FAILED(err)) {
  553. _Py_ExitInitError(err);
  554. }
  555. dump_config();
  556. Py_Finalize();
  557. return 0;
  558. }
  559. static int test_init_dev_mode(void)
  560. {
  561. _PyCoreConfig config = _PyCoreConfig_INIT;
  562. putenv("PYTHONFAULTHANDLER=");
  563. putenv("PYTHONMALLOC=");
  564. config.dev_mode = 1;
  565. config.program_name = L"./_testembed";
  566. _PyInitError err = _Py_InitializeFromConfig(&config);
  567. if (_Py_INIT_FAILED(err)) {
  568. _Py_ExitInitError(err);
  569. }
  570. dump_config();
  571. Py_Finalize();
  572. return 0;
  573. }
  574. static int test_init_read_set(void)
  575. {
  576. _PyInitError err;
  577. _PyCoreConfig config = _PyCoreConfig_INIT;
  578. err = _PyCoreConfig_DecodeLocale(&config.program_name, "./init_read_set");
  579. if (_Py_INIT_FAILED(err)) {
  580. goto fail;
  581. }
  582. err = _PyCoreConfig_Read(&config);
  583. if (_Py_INIT_FAILED(err)) {
  584. goto fail;
  585. }
  586. if (_PyWstrList_Append(&config.module_search_paths,
  587. L"init_read_set_path") < 0) {
  588. err = _Py_INIT_NO_MEMORY();
  589. goto fail;
  590. }
  591. /* override executable computed by _PyCoreConfig_Read() */
  592. err = _PyCoreConfig_SetString(&config.executable, L"my_executable");
  593. if (_Py_INIT_FAILED(err)) {
  594. goto fail;
  595. }
  596. err = _Py_InitializeFromConfig(&config);
  597. _PyCoreConfig_Clear(&config);
  598. if (_Py_INIT_FAILED(err)) {
  599. goto fail;
  600. }
  601. dump_config();
  602. Py_Finalize();
  603. return 0;
  604. fail:
  605. _Py_ExitInitError(err);
  606. }
  607. wchar_t *init_main_argv[] = {
  608. L"python3", L"-c",
  609. (L"import _testinternalcapi, json; "
  610. L"print(json.dumps(_testinternalcapi.get_configs()))"),
  611. L"arg2"};
  612. static void configure_init_main(_PyCoreConfig *config)
  613. {
  614. config->argv.length = Py_ARRAY_LENGTH(init_main_argv);
  615. config->argv.items = init_main_argv;
  616. config->program_name = L"./python3";
  617. }
  618. static int test_init_run_main(void)
  619. {
  620. _PyCoreConfig config = _PyCoreConfig_INIT;
  621. configure_init_main(&config);
  622. _PyInitError err = _Py_InitializeFromConfig(&config);
  623. if (_Py_INIT_FAILED(err)) {
  624. _Py_ExitInitError(err);
  625. }
  626. return _Py_RunMain();
  627. }
  628. static int test_init_main(void)
  629. {
  630. _PyCoreConfig config = _PyCoreConfig_INIT;
  631. configure_init_main(&config);
  632. config._init_main = 0;
  633. _PyInitError err = _Py_InitializeFromConfig(&config);
  634. if (_Py_INIT_FAILED(err)) {
  635. _Py_ExitInitError(err);
  636. }
  637. /* sys.stdout don't exist yet: it is created by _Py_InitializeMain() */
  638. int res = PyRun_SimpleString(
  639. "import sys; "
  640. "print('Run Python code before _Py_InitializeMain', "
  641. "file=sys.stderr)");
  642. if (res < 0) {
  643. exit(1);
  644. }
  645. err = _Py_InitializeMain();
  646. if (_Py_INIT_FAILED(err)) {
  647. _Py_ExitInitError(err);
  648. }
  649. return _Py_RunMain();
  650. }
  651. static int test_run_main(void)
  652. {
  653. _PyCoreConfig config = _PyCoreConfig_INIT;
  654. wchar_t *argv[] = {L"python3", L"-c",
  655. (L"import sys; "
  656. L"print(f'_Py_RunMain(): sys.argv={sys.argv}')"),
  657. L"arg2"};
  658. config.argv.length = Py_ARRAY_LENGTH(argv);
  659. config.argv.items = argv;
  660. config.program_name = L"./python3";
  661. _PyInitError err = _Py_InitializeFromConfig(&config);
  662. if (_Py_INIT_FAILED(err)) {
  663. _Py_ExitInitError(err);
  664. }
  665. return _Py_RunMain();
  666. }
  667. /* *********************************************************
  668. * List of test cases and the function that implements it.
  669. *
  670. * Names are compared case-sensitively with the first
  671. * argument. If no match is found, or no first argument was
  672. * provided, the names of all test cases are printed and
  673. * the exit code will be -1.
  674. *
  675. * The int returned from test functions is used as the exit
  676. * code, and test_capi treats all non-zero exit codes as a
  677. * failed test.
  678. *********************************************************/
  679. struct TestCase
  680. {
  681. const char *name;
  682. int (*func)(void);
  683. };
  684. static struct TestCase TestCases[] = {
  685. { "forced_io_encoding", test_forced_io_encoding },
  686. { "repeated_init_and_subinterpreters", test_repeated_init_and_subinterpreters },
  687. { "pre_initialization_api", test_pre_initialization_api },
  688. { "pre_initialization_sys_options", test_pre_initialization_sys_options },
  689. { "bpo20891", test_bpo20891 },
  690. { "initialize_twice", test_initialize_twice },
  691. { "initialize_pymain", test_initialize_pymain },
  692. { "init_default_config", test_init_default_config },
  693. { "init_global_config", test_init_global_config },
  694. { "init_from_config", test_init_from_config },
  695. { "init_dont_parse_argv", test_init_dont_parse_argv },
  696. { "init_env", test_init_env },
  697. { "init_env_dev_mode", test_init_env_dev_mode },
  698. { "init_env_dev_mode_alloc", test_init_env_dev_mode_alloc },
  699. { "init_dev_mode", test_init_dev_mode },
  700. { "init_isolated", test_init_isolated },
  701. { "preinit_isolated1", test_preinit_isolated1 },
  702. { "preinit_isolated2", test_preinit_isolated2 },
  703. { "init_read_set", test_init_read_set },
  704. { "init_run_main", test_init_run_main },
  705. { "init_main", test_init_main },
  706. { "run_main", test_run_main },
  707. { NULL, NULL }
  708. };
  709. int main(int argc, char *argv[])
  710. {
  711. if (argc > 1) {
  712. for (struct TestCase *tc = TestCases; tc && tc->name; tc++) {
  713. if (strcmp(argv[1], tc->name) == 0)
  714. return (*tc->func)();
  715. }
  716. }
  717. /* No match found, or no test name provided, so display usage */
  718. printf("Python " PY_VERSION " _testembed executable for embedded interpreter tests\n"
  719. "Normally executed via 'EmbeddingTests' in Lib/test/test_embed.py\n\n"
  720. "Usage: %s TESTNAME\n\nAll available tests:\n", argv[0]);
  721. for (struct TestCase *tc = TestCases; tc && tc->name; tc++) {
  722. printf(" %s\n", tc->name);
  723. }
  724. /* Non-zero exit code will cause test_embed.py tests to fail.
  725. This is intentional. */
  726. return -1;
  727. }