(root)/
Python-3.11.7/
Modules/
testcapi_long.h
       1  /* Poor-man's template.  Macros used:
       2     TESTNAME     name of the test (like test_long_api_inner)
       3     TYPENAME     the signed type (like long)
       4     F_S_TO_PY    convert signed to pylong; TYPENAME -> PyObject*
       5     F_PY_TO_S    convert pylong to signed; PyObject* -> TYPENAME
       6     F_U_TO_PY    convert unsigned to pylong; unsigned TYPENAME -> PyObject*
       7     F_PY_TO_U    convert pylong to unsigned; PyObject* -> unsigned TYPENAME
       8  */
       9  
      10  static PyObject *
      11  TESTNAME(PyObject *error(const char*))
      12  {
      13      const int NBITS = sizeof(TYPENAME) * 8;
      14      unsigned TYPENAME base;
      15      PyObject *pyresult;
      16      int i;
      17  
      18      /* Note:  This test lets PyObjects leak if an error is raised.  Since
      19         an error should never be raised, leaks are impossible <wink>. */
      20  
      21      /* Test native -> PyLong -> native roundtrip identity.
      22       * Generate all powers of 2, and test them and their negations,
      23       * plus the numbers +-1 off from them.
      24       */
      25      base = 1;
      26      for (i = 0;
      27           i < NBITS + 1;  /* on last, base overflows to 0 */
      28           ++i, base <<= 1)
      29      {
      30          int j;
      31          for (j = 0; j < 6; ++j) {
      32              TYPENAME in, out;
      33              unsigned TYPENAME uin, uout;
      34  
      35              /* For 0, 1, 2 use base; for 3, 4, 5 use -base */
      36              uin = j < 3 ? base : 0U - base;
      37  
      38              /* For 0 & 3, subtract 1.
      39               * For 1 & 4, leave alone.
      40               * For 2 & 5, add 1.
      41               */
      42              uin += (unsigned TYPENAME)(TYPENAME)(j % 3 - 1);
      43  
      44              pyresult = F_U_TO_PY(uin);
      45              if (pyresult == NULL)
      46                  return error(
      47                   "unsigned unexpected null result");
      48  
      49              uout = F_PY_TO_U(pyresult);
      50              if (uout == (unsigned TYPENAME)-1 && PyErr_Occurred())
      51                  return error(
      52                      "unsigned unexpected -1 result");
      53              if (uout != uin)
      54                  return error(
      55                      "unsigned output != input");
      56              UNBIND(pyresult);
      57  
      58              in = (TYPENAME)uin;
      59              pyresult = F_S_TO_PY(in);
      60              if (pyresult == NULL)
      61                  return error(
      62                      "signed unexpected null result");
      63  
      64              out = F_PY_TO_S(pyresult);
      65              if (out == (TYPENAME)-1 && PyErr_Occurred())
      66                  return error(
      67                      "signed unexpected -1 result");
      68              if (out != in)
      69                  return error(
      70                      "signed output != input");
      71              UNBIND(pyresult);
      72          }
      73      }
      74  
      75      /* Overflow tests.  The loop above ensured that all limit cases that
      76       * should not overflow don't overflow, so all we need to do here is
      77       * provoke one-over-the-limit cases (not exhaustive, but sharp).
      78       */
      79      {
      80          PyObject *one, *x, *y;
      81          TYPENAME out;
      82          unsigned TYPENAME uout;
      83  
      84          one = PyLong_FromLong(1);
      85          if (one == NULL)
      86              return error(
      87                  "unexpected NULL from PyLong_FromLong");
      88  
      89          /* Unsigned complains about -1? */
      90          x = PyNumber_Negative(one);
      91          if (x == NULL)
      92              return error(
      93                  "unexpected NULL from PyNumber_Negative");
      94  
      95          uout = F_PY_TO_U(x);
      96          if (uout != (unsigned TYPENAME)-1 || !PyErr_Occurred())
      97              return error(
      98                  "PyLong_AsUnsignedXXX(-1) didn't complain");
      99          if (!PyErr_ExceptionMatches(PyExc_OverflowError))
     100              return error(
     101                  "PyLong_AsUnsignedXXX(-1) raised "
     102                  "something other than OverflowError");
     103          PyErr_Clear();
     104          UNBIND(x);
     105  
     106          /* Unsigned complains about 2**NBITS? */
     107          y = PyLong_FromLong((long)NBITS);
     108          if (y == NULL)
     109              return error(
     110                  "unexpected NULL from PyLong_FromLong");
     111  
     112          x = PyNumber_Lshift(one, y); /* 1L << NBITS, == 2**NBITS */
     113          UNBIND(y);
     114          if (x == NULL)
     115              return error(
     116                  "unexpected NULL from PyNumber_Lshift");
     117  
     118          uout = F_PY_TO_U(x);
     119          if (uout != (unsigned TYPENAME)-1 || !PyErr_Occurred())
     120              return error(
     121                  "PyLong_AsUnsignedXXX(2**NBITS) didn't "
     122                  "complain");
     123          if (!PyErr_ExceptionMatches(PyExc_OverflowError))
     124              return error(
     125                  "PyLong_AsUnsignedXXX(2**NBITS) raised "
     126                  "something other than OverflowError");
     127          PyErr_Clear();
     128  
     129          /* Signed complains about 2**(NBITS-1)?
     130             x still has 2**NBITS. */
     131          y = PyNumber_Rshift(x, one); /* 2**(NBITS-1) */
     132          UNBIND(x);
     133          if (y == NULL)
     134              return error(
     135                  "unexpected NULL from PyNumber_Rshift");
     136  
     137          out = F_PY_TO_S(y);
     138          if (out != (TYPENAME)-1 || !PyErr_Occurred())
     139              return error(
     140                  "PyLong_AsXXX(2**(NBITS-1)) didn't "
     141                  "complain");
     142          if (!PyErr_ExceptionMatches(PyExc_OverflowError))
     143              return error(
     144                  "PyLong_AsXXX(2**(NBITS-1)) raised "
     145                  "something other than OverflowError");
     146          PyErr_Clear();
     147  
     148          /* Signed complains about -2**(NBITS-1)-1?;
     149             y still has 2**(NBITS-1). */
     150          x = PyNumber_Negative(y);  /* -(2**(NBITS-1)) */
     151          UNBIND(y);
     152          if (x == NULL)
     153              return error(
     154                  "unexpected NULL from PyNumber_Negative");
     155  
     156          y = PyNumber_Subtract(x, one); /* -(2**(NBITS-1))-1 */
     157          UNBIND(x);
     158          if (y == NULL)
     159              return error(
     160                  "unexpected NULL from PyNumber_Subtract");
     161  
     162          out = F_PY_TO_S(y);
     163          if (out != (TYPENAME)-1 || !PyErr_Occurred())
     164              return error(
     165                  "PyLong_AsXXX(-2**(NBITS-1)-1) didn't "
     166                  "complain");
     167          if (!PyErr_ExceptionMatches(PyExc_OverflowError))
     168              return error(
     169                  "PyLong_AsXXX(-2**(NBITS-1)-1) raised "
     170                  "something other than OverflowError");
     171          PyErr_Clear();
     172          UNBIND(y);
     173  
     174          Py_XDECREF(x);
     175          Py_XDECREF(y);
     176          Py_DECREF(one);
     177      }
     178  
     179      /* Test F_PY_TO_{S,U} on non-pylong input. This should raise a TypeError. */
     180      {
     181          TYPENAME out;
     182          unsigned TYPENAME uout;
     183  
     184          Py_INCREF(Py_None);
     185  
     186          out = F_PY_TO_S(Py_None);
     187          if (out != (TYPENAME)-1 || !PyErr_Occurred())
     188              return error("PyLong_AsXXX(None) didn't complain");
     189          if (!PyErr_ExceptionMatches(PyExc_TypeError))
     190              return error("PyLong_AsXXX(None) raised "
     191                           "something other than TypeError");
     192          PyErr_Clear();
     193  
     194          uout = F_PY_TO_U(Py_None);
     195          if (uout != (unsigned TYPENAME)-1 || !PyErr_Occurred())
     196              return error("PyLong_AsXXX(None) didn't complain");
     197          if (!PyErr_ExceptionMatches(PyExc_TypeError))
     198              return error("PyLong_AsXXX(None) raised "
     199                           "something other than TypeError");
     200          PyErr_Clear();
     201  
     202          Py_DECREF(Py_None);
     203      }
     204  
     205      Py_INCREF(Py_None);
     206      return Py_None;
     207  }