LCOV - code coverage report
Current view: top level - Modules - _testinternalcapi.c (source / functions) Hit Total Coverage
Test: CPython 3.12 LCOV report [commit 5e6661bce9] Lines: 31 349 8.9 %
Date: 2023-03-20 08:15:36 Functions: 8 36 22.2 %
Branches: 8 214 3.7 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * C Extension module to test Python internal C APIs (Include/internal).
       3                 :            :  */
       4                 :            : 
       5                 :            : #ifndef Py_BUILD_CORE_BUILTIN
       6                 :            : #  define Py_BUILD_CORE_MODULE 1
       7                 :            : #endif
       8                 :            : 
       9                 :            : /* Always enable assertions */
      10                 :            : #undef NDEBUG
      11                 :            : 
      12                 :            : #define PY_SSIZE_T_CLEAN
      13                 :            : 
      14                 :            : #include "Python.h"
      15                 :            : #include "pycore_atomic_funcs.h" // _Py_atomic_int_get()
      16                 :            : #include "pycore_bitutils.h"     // _Py_bswap32()
      17                 :            : #include "pycore_compile.h"      // _PyCompile_CodeGen, _PyCompile_OptimizeCfg
      18                 :            : #include "pycore_fileutils.h"    // _Py_normpath
      19                 :            : #include "pycore_frame.h"        // _PyInterpreterFrame
      20                 :            : #include "pycore_gc.h"           // PyGC_Head
      21                 :            : #include "pycore_hashtable.h"    // _Py_hashtable_new()
      22                 :            : #include "pycore_initconfig.h"   // _Py_GetConfigsAsDict()
      23                 :            : #include "pycore_pathconfig.h"   // _PyPathConfig_ClearGlobal()
      24                 :            : #include "pycore_interp.h"       // _PyInterpreterState_GetConfigCopy()
      25                 :            : #include "pycore_pyerrors.h"     // _Py_UTF8_Edit_Cost()
      26                 :            : #include "pycore_pystate.h"      // _PyThreadState_GET()
      27                 :            : #include "osdefs.h"              // MAXPATHLEN
      28                 :            : 
      29                 :            : #include "clinic/_testinternalcapi.c.h"
      30                 :            : 
      31                 :            : 
      32                 :            : #define MODULE_NAME "_testinternalcapi"
      33                 :            : 
      34                 :            : 
      35                 :            : static PyObject *
      36                 :          0 : _get_current_module(void)
      37                 :            : {
      38                 :            :     // We ensured it was imported in _run_script().
      39                 :          0 :     PyObject *name = PyUnicode_FromString(MODULE_NAME);
      40         [ #  # ]:          0 :     if (name == NULL) {
      41                 :          0 :         return NULL;
      42                 :            :     }
      43                 :          0 :     PyObject *mod = PyImport_GetModule(name);
      44                 :          0 :     Py_DECREF(name);
      45         [ #  # ]:          0 :     if (mod == NULL) {
      46                 :          0 :         return NULL;
      47                 :            :     }
      48         [ #  # ]:          0 :     assert(mod != Py_None);
      49                 :          0 :     return mod;
      50                 :            : }
      51                 :            : 
      52                 :            : 
      53                 :            : /* module state *************************************************************/
      54                 :            : 
      55                 :            : typedef struct {
      56                 :            :     PyObject *record_list;
      57                 :            : } module_state;
      58                 :            : 
      59                 :            : static inline module_state *
      60                 :          8 : get_module_state(PyObject *mod)
      61                 :            : {
      62         [ -  + ]:          8 :     assert(mod != NULL);
      63                 :          8 :     module_state *state = PyModule_GetState(mod);
      64         [ -  + ]:          8 :     assert(state != NULL);
      65                 :          8 :     return state;
      66                 :            : }
      67                 :            : 
      68                 :            : static int
      69                 :          6 : traverse_module_state(module_state *state, visitproc visit, void *arg)
      70                 :            : {
      71   [ -  +  -  - ]:          6 :     Py_VISIT(state->record_list);
      72                 :          6 :     return 0;
      73                 :            : }
      74                 :            : 
      75                 :            : static int
      76                 :          2 : clear_module_state(module_state *state)
      77                 :            : {
      78         [ -  + ]:          2 :     Py_CLEAR(state->record_list);
      79                 :          2 :     return 0;
      80                 :            : }
      81                 :            : 
      82                 :            : 
      83                 :            : /* module functions *********************************************************/
      84                 :            : 
      85                 :            : /*[clinic input]
      86                 :            : module _testinternalcapi
      87                 :            : [clinic start generated code]*/
      88                 :            : /*[clinic end generated code: output=da39a3ee5e6b4b0d input=7bb583d8c9eb9a78]*/
      89                 :            : static PyObject *
      90                 :          0 : get_configs(PyObject *self, PyObject *Py_UNUSED(args))
      91                 :            : {
      92                 :          0 :     return _Py_GetConfigsAsDict();
      93                 :            : }
      94                 :            : 
      95                 :            : 
      96                 :            : static PyObject*
      97                 :          0 : get_recursion_depth(PyObject *self, PyObject *Py_UNUSED(args))
      98                 :            : {
      99                 :          0 :     PyThreadState *tstate = _PyThreadState_GET();
     100                 :            : 
     101                 :          0 :     return PyLong_FromLong(tstate->py_recursion_limit - tstate->py_recursion_remaining);
     102                 :            : }
     103                 :            : 
     104                 :            : 
     105                 :            : static PyObject*
     106                 :          0 : test_bswap(PyObject *self, PyObject *Py_UNUSED(args))
     107                 :            : {
     108                 :          0 :     uint16_t u16 = _Py_bswap16(UINT16_C(0x3412));
     109         [ #  # ]:          0 :     if (u16 != UINT16_C(0x1234)) {
     110                 :          0 :         PyErr_Format(PyExc_AssertionError,
     111                 :            :                      "_Py_bswap16(0x3412) returns %u", u16);
     112                 :          0 :         return NULL;
     113                 :            :     }
     114                 :            : 
     115                 :          0 :     uint32_t u32 = _Py_bswap32(UINT32_C(0x78563412));
     116         [ #  # ]:          0 :     if (u32 != UINT32_C(0x12345678)) {
     117                 :          0 :         PyErr_Format(PyExc_AssertionError,
     118                 :            :                      "_Py_bswap32(0x78563412) returns %lu", u32);
     119                 :          0 :         return NULL;
     120                 :            :     }
     121                 :            : 
     122                 :          0 :     uint64_t u64 = _Py_bswap64(UINT64_C(0xEFCDAB9078563412));
     123         [ #  # ]:          0 :     if (u64 != UINT64_C(0x1234567890ABCDEF)) {
     124                 :          0 :         PyErr_Format(PyExc_AssertionError,
     125                 :            :                      "_Py_bswap64(0xEFCDAB9078563412) returns %llu", u64);
     126                 :          0 :         return NULL;
     127                 :            :     }
     128                 :            : 
     129                 :          0 :     Py_RETURN_NONE;
     130                 :            : }
     131                 :            : 
     132                 :            : 
     133                 :            : static int
     134                 :          0 : check_popcount(uint32_t x, int expected)
     135                 :            : {
     136                 :            :     // Use volatile to prevent the compiler to optimize out the whole test
     137                 :          0 :     volatile uint32_t u = x;
     138                 :          0 :     int bits = _Py_popcount32(u);
     139         [ #  # ]:          0 :     if (bits != expected) {
     140                 :          0 :         PyErr_Format(PyExc_AssertionError,
     141                 :            :                      "_Py_popcount32(%lu) returns %i, expected %i",
     142                 :            :                      (unsigned long)x, bits, expected);
     143                 :          0 :         return -1;
     144                 :            :     }
     145                 :          0 :     return 0;
     146                 :            : }
     147                 :            : 
     148                 :            : 
     149                 :            : static PyObject*
     150                 :          0 : test_popcount(PyObject *self, PyObject *Py_UNUSED(args))
     151                 :            : {
     152                 :            : #define CHECK(X, RESULT) \
     153                 :            :     do { \
     154                 :            :         if (check_popcount(X, RESULT) < 0) { \
     155                 :            :             return NULL; \
     156                 :            :         } \
     157                 :            :     } while (0)
     158                 :            : 
     159         [ #  # ]:          0 :     CHECK(0, 0);
     160         [ #  # ]:          0 :     CHECK(1, 1);
     161         [ #  # ]:          0 :     CHECK(0x08080808, 4);
     162         [ #  # ]:          0 :     CHECK(0x10000001, 2);
     163         [ #  # ]:          0 :     CHECK(0x10101010, 4);
     164         [ #  # ]:          0 :     CHECK(0x10204080, 4);
     165         [ #  # ]:          0 :     CHECK(0xDEADCAFE, 22);
     166         [ #  # ]:          0 :     CHECK(0xFFFFFFFF, 32);
     167                 :          0 :     Py_RETURN_NONE;
     168                 :            : 
     169                 :            : #undef CHECK
     170                 :            : }
     171                 :            : 
     172                 :            : 
     173                 :            : static int
     174                 :          0 : check_bit_length(unsigned long x, int expected)
     175                 :            : {
     176                 :            :     // Use volatile to prevent the compiler to optimize out the whole test
     177                 :          0 :     volatile unsigned long u = x;
     178                 :          0 :     int len = _Py_bit_length(u);
     179         [ #  # ]:          0 :     if (len != expected) {
     180                 :          0 :         PyErr_Format(PyExc_AssertionError,
     181                 :            :                      "_Py_bit_length(%lu) returns %i, expected %i",
     182                 :            :                      x, len, expected);
     183                 :          0 :         return -1;
     184                 :            :     }
     185                 :          0 :     return 0;
     186                 :            : }
     187                 :            : 
     188                 :            : 
     189                 :            : static PyObject*
     190                 :          0 : test_bit_length(PyObject *self, PyObject *Py_UNUSED(args))
     191                 :            : {
     192                 :            : #define CHECK(X, RESULT) \
     193                 :            :     do { \
     194                 :            :         if (check_bit_length(X, RESULT) < 0) { \
     195                 :            :             return NULL; \
     196                 :            :         } \
     197                 :            :     } while (0)
     198                 :            : 
     199         [ #  # ]:          0 :     CHECK(0, 0);
     200         [ #  # ]:          0 :     CHECK(1, 1);
     201         [ #  # ]:          0 :     CHECK(0x1000, 13);
     202         [ #  # ]:          0 :     CHECK(0x1234, 13);
     203         [ #  # ]:          0 :     CHECK(0x54321, 19);
     204         [ #  # ]:          0 :     CHECK(0x7FFFFFFF, 31);
     205         [ #  # ]:          0 :     CHECK(0xFFFFFFFF, 32);
     206                 :          0 :     Py_RETURN_NONE;
     207                 :            : 
     208                 :            : #undef CHECK
     209                 :            : }
     210                 :            : 
     211                 :            : 
     212                 :            : #define TO_PTR(ch) ((void*)(uintptr_t)ch)
     213                 :            : #define FROM_PTR(ptr) ((uintptr_t)ptr)
     214                 :            : #define VALUE(key) (1 + ((int)(key) - 'a'))
     215                 :            : 
     216                 :            : static Py_uhash_t
     217                 :          0 : hash_char(const void *key)
     218                 :            : {
     219                 :          0 :     char ch = (char)FROM_PTR(key);
     220                 :          0 :     return ch;
     221                 :            : }
     222                 :            : 
     223                 :            : 
     224                 :            : static int
     225                 :          0 : hashtable_cb(_Py_hashtable_t *table,
     226                 :            :              const void *key_ptr, const void *value_ptr,
     227                 :            :              void *user_data)
     228                 :            : {
     229                 :          0 :     int *count = (int *)user_data;
     230                 :          0 :     char key = (char)FROM_PTR(key_ptr);
     231                 :          0 :     int value = (int)FROM_PTR(value_ptr);
     232         [ #  # ]:          0 :     assert(value == VALUE(key));
     233                 :          0 :     *count += 1;
     234                 :          0 :     return 0;
     235                 :            : }
     236                 :            : 
     237                 :            : 
     238                 :            : static PyObject*
     239                 :          0 : test_hashtable(PyObject *self, PyObject *Py_UNUSED(args))
     240                 :            : {
     241                 :          0 :     _Py_hashtable_t *table = _Py_hashtable_new(hash_char,
     242                 :            :                                                _Py_hashtable_compare_direct);
     243         [ #  # ]:          0 :     if (table == NULL) {
     244                 :          0 :         return PyErr_NoMemory();
     245                 :            :     }
     246                 :            : 
     247                 :            :     // Using an newly allocated table must not crash
     248         [ #  # ]:          0 :     assert(table->nentries == 0);
     249         [ #  # ]:          0 :     assert(table->nbuckets > 0);
     250         [ #  # ]:          0 :     assert(_Py_hashtable_get(table, TO_PTR('x')) == NULL);
     251                 :            : 
     252                 :            :     // Test _Py_hashtable_set()
     253                 :            :     char key;
     254         [ #  # ]:          0 :     for (key='a'; key <= 'z'; key++) {
     255                 :          0 :         int value = VALUE(key);
     256         [ #  # ]:          0 :         if (_Py_hashtable_set(table, TO_PTR(key), TO_PTR(value)) < 0) {
     257                 :          0 :             _Py_hashtable_destroy(table);
     258                 :          0 :             return PyErr_NoMemory();
     259                 :            :         }
     260                 :            :     }
     261         [ #  # ]:          0 :     assert(table->nentries == 26);
     262         [ #  # ]:          0 :     assert(table->nbuckets > table->nentries);
     263                 :            : 
     264                 :            :     // Test _Py_hashtable_get_entry()
     265         [ #  # ]:          0 :     for (key='a'; key <= 'z'; key++) {
     266                 :          0 :         _Py_hashtable_entry_t *entry = _Py_hashtable_get_entry(table, TO_PTR(key));
     267         [ #  # ]:          0 :         assert(entry != NULL);
     268         [ #  # ]:          0 :         assert(entry->key == TO_PTR(key));
     269         [ #  # ]:          0 :         assert(entry->value == TO_PTR(VALUE(key)));
     270                 :            :     }
     271                 :            : 
     272                 :            :     // Test _Py_hashtable_get()
     273         [ #  # ]:          0 :     for (key='a'; key <= 'z'; key++) {
     274                 :          0 :         void *value_ptr = _Py_hashtable_get(table, TO_PTR(key));
     275         [ #  # ]:          0 :         assert((int)FROM_PTR(value_ptr) == VALUE(key));
     276                 :            :     }
     277                 :            : 
     278                 :            :     // Test _Py_hashtable_steal()
     279                 :          0 :     key = 'p';
     280                 :          0 :     void *value_ptr = _Py_hashtable_steal(table, TO_PTR(key));
     281         [ #  # ]:          0 :     assert((int)FROM_PTR(value_ptr) == VALUE(key));
     282         [ #  # ]:          0 :     assert(table->nentries == 25);
     283         [ #  # ]:          0 :     assert(_Py_hashtable_get_entry(table, TO_PTR(key)) == NULL);
     284                 :            : 
     285                 :            :     // Test _Py_hashtable_foreach()
     286                 :          0 :     int count = 0;
     287                 :          0 :     int res = _Py_hashtable_foreach(table, hashtable_cb, &count);
     288         [ #  # ]:          0 :     assert(res == 0);
     289         [ #  # ]:          0 :     assert(count == 25);
     290                 :            : 
     291                 :            :     // Test _Py_hashtable_clear()
     292                 :          0 :     _Py_hashtable_clear(table);
     293         [ #  # ]:          0 :     assert(table->nentries == 0);
     294         [ #  # ]:          0 :     assert(table->nbuckets > 0);
     295         [ #  # ]:          0 :     assert(_Py_hashtable_get(table, TO_PTR('x')) == NULL);
     296                 :            : 
     297                 :          0 :     _Py_hashtable_destroy(table);
     298                 :          0 :     Py_RETURN_NONE;
     299                 :            : }
     300                 :            : 
     301                 :            : 
     302                 :            : static PyObject *
     303                 :          0 : test_get_config(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args))
     304                 :            : {
     305                 :            :     PyConfig config;
     306                 :          0 :     PyConfig_InitIsolatedConfig(&config);
     307         [ #  # ]:          0 :     if (_PyInterpreterState_GetConfigCopy(&config) < 0) {
     308                 :          0 :         PyConfig_Clear(&config);
     309                 :          0 :         return NULL;
     310                 :            :     }
     311                 :          0 :     PyObject *dict = _PyConfig_AsDict(&config);
     312                 :          0 :     PyConfig_Clear(&config);
     313                 :          0 :     return dict;
     314                 :            : }
     315                 :            : 
     316                 :            : 
     317                 :            : static PyObject *
     318                 :          0 : test_set_config(PyObject *Py_UNUSED(self), PyObject *dict)
     319                 :            : {
     320                 :            :     PyConfig config;
     321                 :          0 :     PyConfig_InitIsolatedConfig(&config);
     322         [ #  # ]:          0 :     if (_PyConfig_FromDict(&config, dict) < 0) {
     323                 :          0 :         goto error;
     324                 :            :     }
     325         [ #  # ]:          0 :     if (_PyInterpreterState_SetConfig(&config) < 0) {
     326                 :          0 :         goto error;
     327                 :            :     }
     328                 :          0 :     PyConfig_Clear(&config);
     329                 :          0 :     Py_RETURN_NONE;
     330                 :            : 
     331                 :          0 : error:
     332                 :          0 :     PyConfig_Clear(&config);
     333                 :          0 :     return NULL;
     334                 :            : }
     335                 :            : 
     336                 :            : 
     337                 :            : static PyObject *
     338                 :          0 : test_reset_path_config(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(arg))
     339                 :            : {
     340                 :          0 :     _PyPathConfig_ClearGlobal();
     341                 :          0 :     Py_RETURN_NONE;
     342                 :            : }
     343                 :            : 
     344                 :            : 
     345                 :            : static PyObject*
     346                 :          0 : test_atomic_funcs(PyObject *self, PyObject *Py_UNUSED(args))
     347                 :            : {
     348                 :            :     // Test _Py_atomic_size_get() and _Py_atomic_size_set()
     349                 :          0 :     Py_ssize_t var = 1;
     350                 :          0 :     _Py_atomic_size_set(&var, 2);
     351         [ #  # ]:          0 :     assert(_Py_atomic_size_get(&var) == 2);
     352                 :          0 :     Py_RETURN_NONE;
     353                 :            : }
     354                 :            : 
     355                 :            : 
     356                 :            : static int
     357                 :          0 : check_edit_cost(const char *a, const char *b, Py_ssize_t expected)
     358                 :            : {
     359                 :          0 :     int ret = -1;
     360                 :          0 :     PyObject *a_obj = NULL;
     361                 :          0 :     PyObject *b_obj = NULL;
     362                 :            : 
     363                 :          0 :     a_obj = PyUnicode_FromString(a);
     364         [ #  # ]:          0 :     if (a_obj == NULL) {
     365                 :          0 :         goto exit;
     366                 :            :     }
     367                 :          0 :     b_obj = PyUnicode_FromString(b);
     368         [ #  # ]:          0 :     if (b_obj == NULL) {
     369                 :          0 :         goto exit;
     370                 :            :     }
     371                 :          0 :     Py_ssize_t result = _Py_UTF8_Edit_Cost(a_obj, b_obj, -1);
     372         [ #  # ]:          0 :     if (result != expected) {
     373                 :          0 :         PyErr_Format(PyExc_AssertionError,
     374                 :            :                      "Edit cost from '%s' to '%s' returns %zd, expected %zd",
     375                 :            :                      a, b, result, expected);
     376                 :          0 :         goto exit;
     377                 :            :     }
     378                 :            :     // Check that smaller max_edits thresholds are exceeded.
     379                 :          0 :     Py_ssize_t max_edits = result;
     380         [ #  # ]:          0 :     while (max_edits > 0) {
     381                 :          0 :         max_edits /= 2;
     382                 :          0 :         Py_ssize_t result2 = _Py_UTF8_Edit_Cost(a_obj, b_obj, max_edits);
     383         [ #  # ]:          0 :         if (result2 <= max_edits) {
     384                 :          0 :             PyErr_Format(PyExc_AssertionError,
     385                 :            :                          "Edit cost from '%s' to '%s' (threshold %zd) "
     386                 :            :                          "returns %zd, expected greater than %zd",
     387                 :            :                          a, b, max_edits, result2, max_edits);
     388                 :          0 :             goto exit;
     389                 :            :         }
     390                 :            :     }
     391                 :            :     // Check that bigger max_edits thresholds don't change anything
     392                 :          0 :     Py_ssize_t result3 = _Py_UTF8_Edit_Cost(a_obj, b_obj, result * 2 + 1);
     393         [ #  # ]:          0 :     if (result3 != result) {
     394                 :          0 :         PyErr_Format(PyExc_AssertionError,
     395                 :            :                      "Edit cost from '%s' to '%s' (threshold %zd) "
     396                 :            :                      "returns %zd, expected %zd",
     397                 :            :                      a, b, result * 2, result3, result);
     398                 :          0 :         goto exit;
     399                 :            :     }
     400                 :          0 :     ret = 0;
     401                 :          0 : exit:
     402                 :          0 :     Py_XDECREF(a_obj);
     403                 :          0 :     Py_XDECREF(b_obj);
     404                 :          0 :     return ret;
     405                 :            : }
     406                 :            : 
     407                 :            : static PyObject *
     408                 :          0 : test_edit_cost(PyObject *self, PyObject *Py_UNUSED(args))
     409                 :            : {
     410                 :            :     #define CHECK(a, b, n) do {              \
     411                 :            :         if (check_edit_cost(a, b, n) < 0) {  \
     412                 :            :             return NULL;                     \
     413                 :            :         }                                    \
     414                 :            :     } while (0)                              \
     415                 :            : 
     416         [ #  # ]:          0 :     CHECK("", "", 0);
     417         [ #  # ]:          0 :     CHECK("", "a", 2);
     418         [ #  # ]:          0 :     CHECK("a", "A", 1);
     419         [ #  # ]:          0 :     CHECK("Apple", "Aple", 2);
     420         [ #  # ]:          0 :     CHECK("Banana", "B@n@n@", 6);
     421         [ #  # ]:          0 :     CHECK("Cherry", "Cherry!", 2);
     422         [ #  # ]:          0 :     CHECK("---0---", "------", 2);
     423         [ #  # ]:          0 :     CHECK("abc", "y", 6);
     424         [ #  # ]:          0 :     CHECK("aa", "bb", 4);
     425         [ #  # ]:          0 :     CHECK("aaaaa", "AAAAA", 5);
     426         [ #  # ]:          0 :     CHECK("wxyz", "wXyZ", 2);
     427         [ #  # ]:          0 :     CHECK("wxyz", "wXyZ123", 8);
     428         [ #  # ]:          0 :     CHECK("Python", "Java", 12);
     429         [ #  # ]:          0 :     CHECK("Java", "C#", 8);
     430         [ #  # ]:          0 :     CHECK("AbstractFoobarManager", "abstract_foobar_manager", 3+2*2);
     431         [ #  # ]:          0 :     CHECK("CPython", "PyPy", 10);
     432         [ #  # ]:          0 :     CHECK("CPython", "pypy", 11);
     433         [ #  # ]:          0 :     CHECK("AttributeError", "AttributeErrop", 2);
     434         [ #  # ]:          0 :     CHECK("AttributeError", "AttributeErrorTests", 10);
     435                 :            : 
     436                 :            :     #undef CHECK
     437                 :          0 :     Py_RETURN_NONE;
     438                 :            : }
     439                 :            : 
     440                 :            : 
     441                 :            : static PyObject *
     442                 :          0 : normalize_path(PyObject *self, PyObject *filename)
     443                 :            : {
     444                 :          0 :     Py_ssize_t size = -1;
     445                 :          0 :     wchar_t *encoded = PyUnicode_AsWideCharString(filename, &size);
     446         [ #  # ]:          0 :     if (encoded == NULL) {
     447                 :          0 :         return NULL;
     448                 :            :     }
     449                 :            : 
     450                 :          0 :     PyObject *result = PyUnicode_FromWideChar(_Py_normpath(encoded, size), -1);
     451                 :          0 :     PyMem_Free(encoded);
     452                 :            : 
     453                 :          0 :     return result;
     454                 :            : }
     455                 :            : 
     456                 :            : static PyObject *
     457                 :          0 : get_getpath_codeobject(PyObject *self, PyObject *Py_UNUSED(args)) {
     458                 :          0 :     return _Py_Get_Getpath_CodeObject();
     459                 :            : }
     460                 :            : 
     461                 :            : 
     462                 :            : static PyObject *
     463                 :          0 : encode_locale_ex(PyObject *self, PyObject *args)
     464                 :            : {
     465                 :            :     PyObject *unicode;
     466                 :          0 :     int current_locale = 0;
     467                 :            :     wchar_t *wstr;
     468                 :          0 :     PyObject *res = NULL;
     469                 :          0 :     const char *errors = NULL;
     470                 :            : 
     471         [ #  # ]:          0 :     if (!PyArg_ParseTuple(args, "U|is", &unicode, &current_locale, &errors)) {
     472                 :          0 :         return NULL;
     473                 :            :     }
     474                 :          0 :     wstr = PyUnicode_AsWideCharString(unicode, NULL);
     475         [ #  # ]:          0 :     if (wstr == NULL) {
     476                 :          0 :         return NULL;
     477                 :            :     }
     478                 :          0 :     _Py_error_handler error_handler = _Py_GetErrorHandler(errors);
     479                 :            : 
     480                 :          0 :     char *str = NULL;
     481                 :            :     size_t error_pos;
     482                 :          0 :     const char *reason = NULL;
     483                 :          0 :     int ret = _Py_EncodeLocaleEx(wstr,
     484                 :            :                                  &str, &error_pos, &reason,
     485                 :            :                                  current_locale, error_handler);
     486                 :          0 :     PyMem_Free(wstr);
     487                 :            : 
     488   [ #  #  #  #  :          0 :     switch(ret) {
                      # ]
     489                 :          0 :     case 0:
     490                 :          0 :         res = PyBytes_FromString(str);
     491                 :          0 :         PyMem_RawFree(str);
     492                 :          0 :         break;
     493                 :          0 :     case -1:
     494                 :          0 :         PyErr_NoMemory();
     495                 :          0 :         break;
     496                 :          0 :     case -2:
     497                 :          0 :         PyErr_Format(PyExc_RuntimeError, "encode error: pos=%zu, reason=%s",
     498                 :            :                      error_pos, reason);
     499                 :          0 :         break;
     500                 :          0 :     case -3:
     501                 :          0 :         PyErr_SetString(PyExc_ValueError, "unsupported error handler");
     502                 :          0 :         break;
     503                 :          0 :     default:
     504                 :          0 :         PyErr_SetString(PyExc_ValueError, "unknown error code");
     505                 :          0 :         break;
     506                 :            :     }
     507                 :          0 :     return res;
     508                 :            : }
     509                 :            : 
     510                 :            : 
     511                 :            : static PyObject *
     512                 :          0 : decode_locale_ex(PyObject *self, PyObject *args)
     513                 :            : {
     514                 :            :     char *str;
     515                 :          0 :     int current_locale = 0;
     516                 :          0 :     PyObject *res = NULL;
     517                 :          0 :     const char *errors = NULL;
     518                 :            : 
     519         [ #  # ]:          0 :     if (!PyArg_ParseTuple(args, "y|is", &str, &current_locale, &errors)) {
     520                 :          0 :         return NULL;
     521                 :            :     }
     522                 :          0 :     _Py_error_handler error_handler = _Py_GetErrorHandler(errors);
     523                 :            : 
     524                 :          0 :     wchar_t *wstr = NULL;
     525                 :          0 :     size_t wlen = 0;
     526                 :          0 :     const char *reason = NULL;
     527                 :          0 :     int ret = _Py_DecodeLocaleEx(str,
     528                 :            :                                  &wstr, &wlen, &reason,
     529                 :            :                                  current_locale, error_handler);
     530                 :            : 
     531   [ #  #  #  #  :          0 :     switch(ret) {
                      # ]
     532                 :          0 :     case 0:
     533                 :          0 :         res = PyUnicode_FromWideChar(wstr, wlen);
     534                 :          0 :         PyMem_RawFree(wstr);
     535                 :          0 :         break;
     536                 :          0 :     case -1:
     537                 :          0 :         PyErr_NoMemory();
     538                 :          0 :         break;
     539                 :          0 :     case -2:
     540                 :          0 :         PyErr_Format(PyExc_RuntimeError, "decode error: pos=%zu, reason=%s",
     541                 :            :                      wlen, reason);
     542                 :          0 :         break;
     543                 :          0 :     case -3:
     544                 :          0 :         PyErr_SetString(PyExc_ValueError, "unsupported error handler");
     545                 :          0 :         break;
     546                 :          0 :     default:
     547                 :          0 :         PyErr_SetString(PyExc_ValueError, "unknown error code");
     548                 :          0 :         break;
     549                 :            :     }
     550                 :          0 :     return res;
     551                 :            : }
     552                 :            : 
     553                 :            : static PyObject *
     554                 :          0 : set_eval_frame_default(PyObject *self, PyObject *Py_UNUSED(args))
     555                 :            : {
     556                 :          0 :     module_state *state = get_module_state(self);
     557                 :          0 :     _PyInterpreterState_SetEvalFrameFunc(PyInterpreterState_Get(), _PyEval_EvalFrameDefault);
     558         [ #  # ]:          0 :     Py_CLEAR(state->record_list);
     559                 :          0 :     Py_RETURN_NONE;
     560                 :            : }
     561                 :            : 
     562                 :            : static PyObject *
     563                 :          0 : record_eval(PyThreadState *tstate, struct _PyInterpreterFrame *f, int exc)
     564                 :            : {
     565         [ #  # ]:          0 :     if (PyFunction_Check(f->f_funcobj)) {
     566                 :          0 :         PyObject *module = _get_current_module();
     567         [ #  # ]:          0 :         assert(module != NULL);
     568                 :          0 :         module_state *state = get_module_state(module);
     569                 :          0 :         Py_DECREF(module);
     570                 :          0 :         PyList_Append(state->record_list, ((PyFunctionObject *)f->f_funcobj)->func_name);
     571                 :            :     }
     572                 :          0 :     return _PyEval_EvalFrameDefault(tstate, f, exc);
     573                 :            : }
     574                 :            : 
     575                 :            : 
     576                 :            : static PyObject *
     577                 :          0 : set_eval_frame_record(PyObject *self, PyObject *list)
     578                 :            : {
     579                 :          0 :     module_state *state = get_module_state(self);
     580         [ #  # ]:          0 :     if (!PyList_Check(list)) {
     581                 :          0 :         PyErr_SetString(PyExc_TypeError, "argument must be a list");
     582                 :          0 :         return NULL;
     583                 :            :     }
     584                 :          0 :     Py_XSETREF(state->record_list, Py_NewRef(list));
     585                 :          0 :     _PyInterpreterState_SetEvalFrameFunc(PyInterpreterState_Get(), record_eval);
     586                 :          0 :     Py_RETURN_NONE;
     587                 :            : }
     588                 :            : 
     589                 :            : /*[clinic input]
     590                 :            : 
     591                 :            : _testinternalcapi.compiler_codegen -> object
     592                 :            : 
     593                 :            :   ast: object
     594                 :            :   filename: object
     595                 :            :   optimize: int
     596                 :            : 
     597                 :            : Apply compiler code generation to an AST.
     598                 :            : [clinic start generated code]*/
     599                 :            : 
     600                 :            : static PyObject *
     601                 :          0 : _testinternalcapi_compiler_codegen_impl(PyObject *module, PyObject *ast,
     602                 :            :                                         PyObject *filename, int optimize)
     603                 :            : /*[clinic end generated code: output=fbbbbfb34700c804 input=e9fbe6562f7f75e4]*/
     604                 :            : {
     605                 :          0 :     PyCompilerFlags *flags = NULL;
     606                 :          0 :     return _PyCompile_CodeGen(ast, filename, flags, optimize);
     607                 :            : }
     608                 :            : 
     609                 :            : 
     610                 :            : /*[clinic input]
     611                 :            : 
     612                 :            : _testinternalcapi.optimize_cfg -> object
     613                 :            : 
     614                 :            :   instructions: object
     615                 :            :   consts: object
     616                 :            : 
     617                 :            : Apply compiler optimizations to an instruction list.
     618                 :            : [clinic start generated code]*/
     619                 :            : 
     620                 :            : static PyObject *
     621                 :          0 : _testinternalcapi_optimize_cfg_impl(PyObject *module, PyObject *instructions,
     622                 :            :                                     PyObject *consts)
     623                 :            : /*[clinic end generated code: output=5412aeafca683c8b input=7e8a3de86ebdd0f9]*/
     624                 :            : {
     625                 :          0 :     return _PyCompile_OptimizeCfg(instructions, consts);
     626                 :            : }
     627                 :            : 
     628                 :            : 
     629                 :            : static PyObject *
     630                 :          0 : get_interp_settings(PyObject *self, PyObject *args)
     631                 :            : {
     632                 :          0 :     int interpid = -1;
     633         [ #  # ]:          0 :     if (!PyArg_ParseTuple(args, "|i:get_interp_settings", &interpid)) {
     634                 :          0 :         return NULL;
     635                 :            :     }
     636                 :            : 
     637                 :          0 :     PyInterpreterState *interp = NULL;
     638         [ #  # ]:          0 :     if (interpid < 0) {
     639                 :          0 :         PyThreadState *tstate = _PyThreadState_GET();
     640         [ #  # ]:          0 :         interp = tstate ? tstate->interp : _PyInterpreterState_Main();
     641                 :            :     }
     642         [ #  # ]:          0 :     else if (interpid == 0) {
     643                 :          0 :         interp = _PyInterpreterState_Main();
     644                 :            :     }
     645                 :            :     else {
     646                 :          0 :         PyErr_Format(PyExc_NotImplementedError,
     647                 :            :                      "%zd", interpid);
     648                 :          0 :         return NULL;
     649                 :            :     }
     650         [ #  # ]:          0 :     assert(interp != NULL);
     651                 :            : 
     652                 :          0 :     PyObject *settings = PyDict_New();
     653         [ #  # ]:          0 :     if (settings == NULL) {
     654                 :          0 :         return NULL;
     655                 :            :     }
     656                 :            : 
     657                 :            :     /* Add the feature flags. */
     658                 :          0 :     PyObject *flags = PyLong_FromUnsignedLong(interp->feature_flags);
     659         [ #  # ]:          0 :     if (flags == NULL) {
     660                 :          0 :         Py_DECREF(settings);
     661                 :          0 :         return NULL;
     662                 :            :     }
     663                 :          0 :     int res = PyDict_SetItemString(settings, "feature_flags", flags);
     664                 :          0 :     Py_DECREF(flags);
     665         [ #  # ]:          0 :     if (res != 0) {
     666                 :          0 :         Py_DECREF(settings);
     667                 :          0 :         return NULL;
     668                 :            :     }
     669                 :            : 
     670                 :          0 :     return settings;
     671                 :            : }
     672                 :            : 
     673                 :            : 
     674                 :            : static PyObject *
     675                 :          0 : clear_extension(PyObject *self, PyObject *args)
     676                 :            : {
     677                 :          0 :     PyObject *name = NULL, *filename = NULL;
     678         [ #  # ]:          0 :     if (!PyArg_ParseTuple(args, "OO:clear_extension", &name, &filename)) {
     679                 :          0 :         return NULL;
     680                 :            :     }
     681         [ #  # ]:          0 :     if (_PyImport_ClearExtension(name, filename) < 0) {
     682                 :          0 :         return NULL;
     683                 :            :     }
     684                 :          0 :     Py_RETURN_NONE;
     685                 :            : }
     686                 :            : 
     687                 :            : 
     688                 :            : static PyMethodDef module_functions[] = {
     689                 :            :     {"get_configs", get_configs, METH_NOARGS},
     690                 :            :     {"get_recursion_depth", get_recursion_depth, METH_NOARGS},
     691                 :            :     {"test_bswap", test_bswap, METH_NOARGS},
     692                 :            :     {"test_popcount", test_popcount, METH_NOARGS},
     693                 :            :     {"test_bit_length", test_bit_length, METH_NOARGS},
     694                 :            :     {"test_hashtable", test_hashtable, METH_NOARGS},
     695                 :            :     {"get_config", test_get_config, METH_NOARGS},
     696                 :            :     {"set_config", test_set_config, METH_O},
     697                 :            :     {"reset_path_config", test_reset_path_config, METH_NOARGS},
     698                 :            :     {"test_atomic_funcs", test_atomic_funcs, METH_NOARGS},
     699                 :            :     {"test_edit_cost", test_edit_cost, METH_NOARGS},
     700                 :            :     {"normalize_path", normalize_path, METH_O, NULL},
     701                 :            :     {"get_getpath_codeobject", get_getpath_codeobject, METH_NOARGS, NULL},
     702                 :            :     {"EncodeLocaleEx", encode_locale_ex, METH_VARARGS},
     703                 :            :     {"DecodeLocaleEx", decode_locale_ex, METH_VARARGS},
     704                 :            :     {"set_eval_frame_default", set_eval_frame_default, METH_NOARGS, NULL},
     705                 :            :     {"set_eval_frame_record", set_eval_frame_record, METH_O, NULL},
     706                 :            :     _TESTINTERNALCAPI_COMPILER_CODEGEN_METHODDEF
     707                 :            :     _TESTINTERNALCAPI_OPTIMIZE_CFG_METHODDEF
     708                 :            :     {"get_interp_settings", get_interp_settings, METH_VARARGS, NULL},
     709                 :            :     {"clear_extension", clear_extension, METH_VARARGS, NULL},
     710                 :            :     {NULL, NULL} /* sentinel */
     711                 :            : };
     712                 :            : 
     713                 :            : 
     714                 :            : /* initialization function */
     715                 :            : 
     716                 :            : static int
     717                 :          1 : module_exec(PyObject *module)
     718                 :            : {
     719         [ -  + ]:          1 :     if (PyModule_AddObject(module, "SIZEOF_PYGC_HEAD",
     720                 :            :                            PyLong_FromSsize_t(sizeof(PyGC_Head))) < 0) {
     721                 :          0 :         return 1;
     722                 :            :     }
     723                 :            : 
     724                 :          1 :     return 0;
     725                 :            : }
     726                 :            : 
     727                 :            : static struct PyModuleDef_Slot module_slots[] = {
     728                 :            :     {Py_mod_exec, module_exec},
     729                 :            :     {0, NULL},
     730                 :            : };
     731                 :            : 
     732                 :            : static int
     733                 :          6 : module_traverse(PyObject *module, visitproc visit, void *arg)
     734                 :            : {
     735                 :          6 :     module_state *state = get_module_state(module);
     736         [ -  + ]:          6 :     assert(state != NULL);
     737                 :          6 :     traverse_module_state(state, visit, arg);
     738                 :          6 :     return 0;
     739                 :            : }
     740                 :            : 
     741                 :            : static int
     742                 :          1 : module_clear(PyObject *module)
     743                 :            : {
     744                 :          1 :     module_state *state = get_module_state(module);
     745         [ -  + ]:          1 :     assert(state != NULL);
     746                 :          1 :     (void)clear_module_state(state);
     747                 :          1 :     return 0;
     748                 :            : }
     749                 :            : 
     750                 :            : static void
     751                 :          1 : module_free(void *module)
     752                 :            : {
     753                 :          1 :     module_state *state = get_module_state(module);
     754         [ -  + ]:          1 :     assert(state != NULL);
     755                 :          1 :     (void)clear_module_state(state);
     756                 :          1 : }
     757                 :            : 
     758                 :            : static struct PyModuleDef _testcapimodule = {
     759                 :            :     .m_base = PyModuleDef_HEAD_INIT,
     760                 :            :     .m_name = MODULE_NAME,
     761                 :            :     .m_doc = NULL,
     762                 :            :     .m_size = sizeof(module_state),
     763                 :            :     .m_methods = module_functions,
     764                 :            :     .m_slots = module_slots,
     765                 :            :     .m_traverse = module_traverse,
     766                 :            :     .m_clear = module_clear,
     767                 :            :     .m_free = (freefunc)module_free,
     768                 :            : };
     769                 :            : 
     770                 :            : 
     771                 :            : PyMODINIT_FUNC
     772                 :          1 : PyInit__testinternalcapi(void)
     773                 :            : {
     774                 :          1 :     return PyModuleDef_Init(&_testcapimodule);
     775                 :            : }

Generated by: LCOV version 1.14