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