LCOV - code coverage report
Current view: top level - Modules - testcapi_long.h (source / functions) Hit Total Coverage
Test: CPython 3.12 LCOV report [commit acb105a7c1f] Lines: 73 98 74.5 %
Date: 2022-07-20 13:12:14 Functions: 2 2 100.0 %
Branches: 41 72 56.9 %

           Branch data     Line data    Source code
       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                 :          2 : TESTNAME(PyObject *error(const char*))
      12                 :            : {
      13                 :          2 :     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                 :          2 :     base = 1;
      26                 :          2 :     for (i = 0;
      27         [ +  + ]:        132 :          i < NBITS + 1;  /* on last, base overflows to 0 */
      28                 :        130 :          ++i, base <<= 1)
      29                 :            :     {
      30                 :            :         int j;
      31         [ +  + ]:        910 :         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         [ +  + ]:        780 :             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                 :        780 :             uin += (unsigned TYPENAME)(TYPENAME)(j % 3 - 1);
      43                 :            : 
      44                 :        780 :             pyresult = F_U_TO_PY(uin);
      45         [ -  + ]:        780 :             if (pyresult == NULL)
      46                 :          0 :                 return error(
      47                 :            :                  "unsigned unexpected null result");
      48                 :            : 
      49                 :        780 :             uout = F_PY_TO_U(pyresult);
      50   [ +  +  -  + ]:        780 :             if (uout == (unsigned TYPENAME)-1 && PyErr_Occurred())
      51                 :          0 :                 return error(
      52                 :            :                     "unsigned unexpected -1 result");
      53         [ -  + ]:        780 :             if (uout != uin)
      54                 :          0 :                 return error(
      55                 :            :                     "unsigned output != input");
      56                 :        780 :             UNBIND(pyresult);
      57                 :            : 
      58                 :        780 :             in = (TYPENAME)uin;
      59                 :        780 :             pyresult = F_S_TO_PY(in);
      60         [ -  + ]:        780 :             if (pyresult == NULL)
      61                 :          0 :                 return error(
      62                 :            :                     "signed unexpected null result");
      63                 :            : 
      64                 :        780 :             out = F_PY_TO_S(pyresult);
      65   [ +  +  -  + ]:        780 :             if (out == (TYPENAME)-1 && PyErr_Occurred())
      66                 :          0 :                 return error(
      67                 :            :                     "signed unexpected -1 result");
      68         [ -  + ]:        780 :             if (out != in)
      69                 :          0 :                 return error(
      70                 :            :                     "signed output != input");
      71                 :        780 :             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                 :          2 :         one = PyLong_FromLong(1);
      85         [ -  + ]:          2 :         if (one == NULL)
      86                 :          0 :             return error(
      87                 :            :                 "unexpected NULL from PyLong_FromLong");
      88                 :            : 
      89                 :            :         /* Unsigned complains about -1? */
      90                 :          2 :         x = PyNumber_Negative(one);
      91         [ -  + ]:          2 :         if (x == NULL)
      92                 :          0 :             return error(
      93                 :            :                 "unexpected NULL from PyNumber_Negative");
      94                 :            : 
      95                 :          2 :         uout = F_PY_TO_U(x);
      96   [ +  -  -  + ]:          2 :         if (uout != (unsigned TYPENAME)-1 || !PyErr_Occurred())
      97                 :          0 :             return error(
      98                 :            :                 "PyLong_AsUnsignedXXX(-1) didn't complain");
      99         [ -  + ]:          2 :         if (!PyErr_ExceptionMatches(PyExc_OverflowError))
     100                 :          0 :             return error(
     101                 :            :                 "PyLong_AsUnsignedXXX(-1) raised "
     102                 :            :                 "something other than OverflowError");
     103                 :          2 :         PyErr_Clear();
     104                 :          2 :         UNBIND(x);
     105                 :            : 
     106                 :            :         /* Unsigned complains about 2**NBITS? */
     107                 :          2 :         y = PyLong_FromLong((long)NBITS);
     108         [ -  + ]:          2 :         if (y == NULL)
     109                 :          0 :             return error(
     110                 :            :                 "unexpected NULL from PyLong_FromLong");
     111                 :            : 
     112                 :          2 :         x = PyNumber_Lshift(one, y); /* 1L << NBITS, == 2**NBITS */
     113                 :          2 :         UNBIND(y);
     114         [ -  + ]:          2 :         if (x == NULL)
     115                 :          0 :             return error(
     116                 :            :                 "unexpected NULL from PyNumber_Lshift");
     117                 :            : 
     118                 :          2 :         uout = F_PY_TO_U(x);
     119   [ +  -  -  + ]:          2 :         if (uout != (unsigned TYPENAME)-1 || !PyErr_Occurred())
     120                 :          0 :             return error(
     121                 :            :                 "PyLong_AsUnsignedXXX(2**NBITS) didn't "
     122                 :            :                 "complain");
     123         [ -  + ]:          2 :         if (!PyErr_ExceptionMatches(PyExc_OverflowError))
     124                 :          0 :             return error(
     125                 :            :                 "PyLong_AsUnsignedXXX(2**NBITS) raised "
     126                 :            :                 "something other than OverflowError");
     127                 :          2 :         PyErr_Clear();
     128                 :            : 
     129                 :            :         /* Signed complains about 2**(NBITS-1)?
     130                 :            :            x still has 2**NBITS. */
     131                 :          2 :         y = PyNumber_Rshift(x, one); /* 2**(NBITS-1) */
     132                 :          2 :         UNBIND(x);
     133         [ -  + ]:          2 :         if (y == NULL)
     134                 :          0 :             return error(
     135                 :            :                 "unexpected NULL from PyNumber_Rshift");
     136                 :            : 
     137                 :          2 :         out = F_PY_TO_S(y);
     138   [ +  -  -  + ]:          2 :         if (out != (TYPENAME)-1 || !PyErr_Occurred())
     139                 :          0 :             return error(
     140                 :            :                 "PyLong_AsXXX(2**(NBITS-1)) didn't "
     141                 :            :                 "complain");
     142         [ -  + ]:          2 :         if (!PyErr_ExceptionMatches(PyExc_OverflowError))
     143                 :          0 :             return error(
     144                 :            :                 "PyLong_AsXXX(2**(NBITS-1)) raised "
     145                 :            :                 "something other than OverflowError");
     146                 :          2 :         PyErr_Clear();
     147                 :            : 
     148                 :            :         /* Signed complains about -2**(NBITS-1)-1?;
     149                 :            :            y still has 2**(NBITS-1). */
     150                 :          2 :         x = PyNumber_Negative(y);  /* -(2**(NBITS-1)) */
     151                 :          2 :         UNBIND(y);
     152         [ -  + ]:          2 :         if (x == NULL)
     153                 :          0 :             return error(
     154                 :            :                 "unexpected NULL from PyNumber_Negative");
     155                 :            : 
     156                 :          2 :         y = PyNumber_Subtract(x, one); /* -(2**(NBITS-1))-1 */
     157                 :          2 :         UNBIND(x);
     158         [ -  + ]:          2 :         if (y == NULL)
     159                 :          0 :             return error(
     160                 :            :                 "unexpected NULL from PyNumber_Subtract");
     161                 :            : 
     162                 :          2 :         out = F_PY_TO_S(y);
     163   [ +  -  -  + ]:          2 :         if (out != (TYPENAME)-1 || !PyErr_Occurred())
     164                 :          0 :             return error(
     165                 :            :                 "PyLong_AsXXX(-2**(NBITS-1)-1) didn't "
     166                 :            :                 "complain");
     167         [ -  + ]:          2 :         if (!PyErr_ExceptionMatches(PyExc_OverflowError))
     168                 :          0 :             return error(
     169                 :            :                 "PyLong_AsXXX(-2**(NBITS-1)-1) raised "
     170                 :            :                 "something other than OverflowError");
     171                 :          2 :         PyErr_Clear();
     172                 :          2 :         UNBIND(y);
     173                 :            : 
     174                 :          2 :         Py_XDECREF(x);
     175                 :          2 :         Py_XDECREF(y);
     176                 :          2 :         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                 :          2 :         Py_INCREF(Py_None);
     185                 :            : 
     186                 :          2 :         out = F_PY_TO_S(Py_None);
     187   [ +  -  -  + ]:          2 :         if (out != (TYPENAME)-1 || !PyErr_Occurred())
     188                 :          0 :             return error("PyLong_AsXXX(None) didn't complain");
     189         [ -  + ]:          2 :         if (!PyErr_ExceptionMatches(PyExc_TypeError))
     190                 :          0 :             return error("PyLong_AsXXX(None) raised "
     191                 :            :                          "something other than TypeError");
     192                 :          2 :         PyErr_Clear();
     193                 :            : 
     194                 :          2 :         uout = F_PY_TO_U(Py_None);
     195   [ +  -  -  + ]:          2 :         if (uout != (unsigned TYPENAME)-1 || !PyErr_Occurred())
     196                 :          0 :             return error("PyLong_AsXXX(None) didn't complain");
     197         [ -  + ]:          2 :         if (!PyErr_ExceptionMatches(PyExc_TypeError))
     198                 :          0 :             return error("PyLong_AsXXX(None) raised "
     199                 :            :                          "something other than TypeError");
     200                 :          2 :         PyErr_Clear();
     201                 :            : 
     202                 :          2 :         Py_DECREF(Py_None);
     203                 :            :     }
     204                 :            : 
     205                 :          2 :     Py_INCREF(Py_None);
     206                 :          2 :     return Py_None;
     207                 :            : }

Generated by: LCOV version 1.14