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 132 : for (i = 0; 27 : 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 : }