LCOV - code coverage report
Current view: | top level - Programs - _testembed.c (source / functions) |  |  | Hit | Total | Coverage
Test: | CPython 3.12 LCOV report [commit 5e6661bce9] |  | Lines: | 0 | 1051 | 0.0 %
Date: | 2023-03-20 08:15:36 |  | Functions: | 0 | 95 | 0.0 %
|  |  | Branches: | 0 | 221 | 0.0 %

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

Generated by: LCOV version 1.14