17db96d56Sopenharmony_ci/* Poor-man's template. Macros used: 27db96d56Sopenharmony_ci TESTNAME name of the test (like test_long_api_inner) 37db96d56Sopenharmony_ci TYPENAME the signed type (like long) 47db96d56Sopenharmony_ci F_S_TO_PY convert signed to pylong; TYPENAME -> PyObject* 57db96d56Sopenharmony_ci F_PY_TO_S convert pylong to signed; PyObject* -> TYPENAME 67db96d56Sopenharmony_ci F_U_TO_PY convert unsigned to pylong; unsigned TYPENAME -> PyObject* 77db96d56Sopenharmony_ci F_PY_TO_U convert pylong to unsigned; PyObject* -> unsigned TYPENAME 87db96d56Sopenharmony_ci*/ 97db96d56Sopenharmony_ci 107db96d56Sopenharmony_cistatic PyObject * 117db96d56Sopenharmony_ciTESTNAME(PyObject *error(const char*)) 127db96d56Sopenharmony_ci{ 137db96d56Sopenharmony_ci const int NBITS = sizeof(TYPENAME) * 8; 147db96d56Sopenharmony_ci unsigned TYPENAME base; 157db96d56Sopenharmony_ci PyObject *pyresult; 167db96d56Sopenharmony_ci int i; 177db96d56Sopenharmony_ci 187db96d56Sopenharmony_ci /* Note: This test lets PyObjects leak if an error is raised. Since 197db96d56Sopenharmony_ci an error should never be raised, leaks are impossible <wink>. */ 207db96d56Sopenharmony_ci 217db96d56Sopenharmony_ci /* Test native -> PyLong -> native roundtrip identity. 227db96d56Sopenharmony_ci * Generate all powers of 2, and test them and their negations, 237db96d56Sopenharmony_ci * plus the numbers +-1 off from them. 247db96d56Sopenharmony_ci */ 257db96d56Sopenharmony_ci base = 1; 267db96d56Sopenharmony_ci for (i = 0; 277db96d56Sopenharmony_ci i < NBITS + 1; /* on last, base overflows to 0 */ 287db96d56Sopenharmony_ci ++i, base <<= 1) 297db96d56Sopenharmony_ci { 307db96d56Sopenharmony_ci int j; 317db96d56Sopenharmony_ci for (j = 0; j < 6; ++j) { 327db96d56Sopenharmony_ci TYPENAME in, out; 337db96d56Sopenharmony_ci unsigned TYPENAME uin, uout; 347db96d56Sopenharmony_ci 357db96d56Sopenharmony_ci /* For 0, 1, 2 use base; for 3, 4, 5 use -base */ 367db96d56Sopenharmony_ci uin = j < 3 ? base : 0U - base; 377db96d56Sopenharmony_ci 387db96d56Sopenharmony_ci /* For 0 & 3, subtract 1. 397db96d56Sopenharmony_ci * For 1 & 4, leave alone. 407db96d56Sopenharmony_ci * For 2 & 5, add 1. 417db96d56Sopenharmony_ci */ 427db96d56Sopenharmony_ci uin += (unsigned TYPENAME)(TYPENAME)(j % 3 - 1); 437db96d56Sopenharmony_ci 447db96d56Sopenharmony_ci pyresult = F_U_TO_PY(uin); 457db96d56Sopenharmony_ci if (pyresult == NULL) 467db96d56Sopenharmony_ci return error( 477db96d56Sopenharmony_ci "unsigned unexpected null result"); 487db96d56Sopenharmony_ci 497db96d56Sopenharmony_ci uout = F_PY_TO_U(pyresult); 507db96d56Sopenharmony_ci if (uout == (unsigned TYPENAME)-1 && PyErr_Occurred()) 517db96d56Sopenharmony_ci return error( 527db96d56Sopenharmony_ci "unsigned unexpected -1 result"); 537db96d56Sopenharmony_ci if (uout != uin) 547db96d56Sopenharmony_ci return error( 557db96d56Sopenharmony_ci "unsigned output != input"); 567db96d56Sopenharmony_ci UNBIND(pyresult); 577db96d56Sopenharmony_ci 587db96d56Sopenharmony_ci in = (TYPENAME)uin; 597db96d56Sopenharmony_ci pyresult = F_S_TO_PY(in); 607db96d56Sopenharmony_ci if (pyresult == NULL) 617db96d56Sopenharmony_ci return error( 627db96d56Sopenharmony_ci "signed unexpected null result"); 637db96d56Sopenharmony_ci 647db96d56Sopenharmony_ci out = F_PY_TO_S(pyresult); 657db96d56Sopenharmony_ci if (out == (TYPENAME)-1 && PyErr_Occurred()) 667db96d56Sopenharmony_ci return error( 677db96d56Sopenharmony_ci "signed unexpected -1 result"); 687db96d56Sopenharmony_ci if (out != in) 697db96d56Sopenharmony_ci return error( 707db96d56Sopenharmony_ci "signed output != input"); 717db96d56Sopenharmony_ci UNBIND(pyresult); 727db96d56Sopenharmony_ci } 737db96d56Sopenharmony_ci } 747db96d56Sopenharmony_ci 757db96d56Sopenharmony_ci /* Overflow tests. The loop above ensured that all limit cases that 767db96d56Sopenharmony_ci * should not overflow don't overflow, so all we need to do here is 777db96d56Sopenharmony_ci * provoke one-over-the-limit cases (not exhaustive, but sharp). 787db96d56Sopenharmony_ci */ 797db96d56Sopenharmony_ci { 807db96d56Sopenharmony_ci PyObject *one, *x, *y; 817db96d56Sopenharmony_ci TYPENAME out; 827db96d56Sopenharmony_ci unsigned TYPENAME uout; 837db96d56Sopenharmony_ci 847db96d56Sopenharmony_ci one = PyLong_FromLong(1); 857db96d56Sopenharmony_ci if (one == NULL) 867db96d56Sopenharmony_ci return error( 877db96d56Sopenharmony_ci "unexpected NULL from PyLong_FromLong"); 887db96d56Sopenharmony_ci 897db96d56Sopenharmony_ci /* Unsigned complains about -1? */ 907db96d56Sopenharmony_ci x = PyNumber_Negative(one); 917db96d56Sopenharmony_ci if (x == NULL) 927db96d56Sopenharmony_ci return error( 937db96d56Sopenharmony_ci "unexpected NULL from PyNumber_Negative"); 947db96d56Sopenharmony_ci 957db96d56Sopenharmony_ci uout = F_PY_TO_U(x); 967db96d56Sopenharmony_ci if (uout != (unsigned TYPENAME)-1 || !PyErr_Occurred()) 977db96d56Sopenharmony_ci return error( 987db96d56Sopenharmony_ci "PyLong_AsUnsignedXXX(-1) didn't complain"); 997db96d56Sopenharmony_ci if (!PyErr_ExceptionMatches(PyExc_OverflowError)) 1007db96d56Sopenharmony_ci return error( 1017db96d56Sopenharmony_ci "PyLong_AsUnsignedXXX(-1) raised " 1027db96d56Sopenharmony_ci "something other than OverflowError"); 1037db96d56Sopenharmony_ci PyErr_Clear(); 1047db96d56Sopenharmony_ci UNBIND(x); 1057db96d56Sopenharmony_ci 1067db96d56Sopenharmony_ci /* Unsigned complains about 2**NBITS? */ 1077db96d56Sopenharmony_ci y = PyLong_FromLong((long)NBITS); 1087db96d56Sopenharmony_ci if (y == NULL) 1097db96d56Sopenharmony_ci return error( 1107db96d56Sopenharmony_ci "unexpected NULL from PyLong_FromLong"); 1117db96d56Sopenharmony_ci 1127db96d56Sopenharmony_ci x = PyNumber_Lshift(one, y); /* 1L << NBITS, == 2**NBITS */ 1137db96d56Sopenharmony_ci UNBIND(y); 1147db96d56Sopenharmony_ci if (x == NULL) 1157db96d56Sopenharmony_ci return error( 1167db96d56Sopenharmony_ci "unexpected NULL from PyNumber_Lshift"); 1177db96d56Sopenharmony_ci 1187db96d56Sopenharmony_ci uout = F_PY_TO_U(x); 1197db96d56Sopenharmony_ci if (uout != (unsigned TYPENAME)-1 || !PyErr_Occurred()) 1207db96d56Sopenharmony_ci return error( 1217db96d56Sopenharmony_ci "PyLong_AsUnsignedXXX(2**NBITS) didn't " 1227db96d56Sopenharmony_ci "complain"); 1237db96d56Sopenharmony_ci if (!PyErr_ExceptionMatches(PyExc_OverflowError)) 1247db96d56Sopenharmony_ci return error( 1257db96d56Sopenharmony_ci "PyLong_AsUnsignedXXX(2**NBITS) raised " 1267db96d56Sopenharmony_ci "something other than OverflowError"); 1277db96d56Sopenharmony_ci PyErr_Clear(); 1287db96d56Sopenharmony_ci 1297db96d56Sopenharmony_ci /* Signed complains about 2**(NBITS-1)? 1307db96d56Sopenharmony_ci x still has 2**NBITS. */ 1317db96d56Sopenharmony_ci y = PyNumber_Rshift(x, one); /* 2**(NBITS-1) */ 1327db96d56Sopenharmony_ci UNBIND(x); 1337db96d56Sopenharmony_ci if (y == NULL) 1347db96d56Sopenharmony_ci return error( 1357db96d56Sopenharmony_ci "unexpected NULL from PyNumber_Rshift"); 1367db96d56Sopenharmony_ci 1377db96d56Sopenharmony_ci out = F_PY_TO_S(y); 1387db96d56Sopenharmony_ci if (out != (TYPENAME)-1 || !PyErr_Occurred()) 1397db96d56Sopenharmony_ci return error( 1407db96d56Sopenharmony_ci "PyLong_AsXXX(2**(NBITS-1)) didn't " 1417db96d56Sopenharmony_ci "complain"); 1427db96d56Sopenharmony_ci if (!PyErr_ExceptionMatches(PyExc_OverflowError)) 1437db96d56Sopenharmony_ci return error( 1447db96d56Sopenharmony_ci "PyLong_AsXXX(2**(NBITS-1)) raised " 1457db96d56Sopenharmony_ci "something other than OverflowError"); 1467db96d56Sopenharmony_ci PyErr_Clear(); 1477db96d56Sopenharmony_ci 1487db96d56Sopenharmony_ci /* Signed complains about -2**(NBITS-1)-1?; 1497db96d56Sopenharmony_ci y still has 2**(NBITS-1). */ 1507db96d56Sopenharmony_ci x = PyNumber_Negative(y); /* -(2**(NBITS-1)) */ 1517db96d56Sopenharmony_ci UNBIND(y); 1527db96d56Sopenharmony_ci if (x == NULL) 1537db96d56Sopenharmony_ci return error( 1547db96d56Sopenharmony_ci "unexpected NULL from PyNumber_Negative"); 1557db96d56Sopenharmony_ci 1567db96d56Sopenharmony_ci y = PyNumber_Subtract(x, one); /* -(2**(NBITS-1))-1 */ 1577db96d56Sopenharmony_ci UNBIND(x); 1587db96d56Sopenharmony_ci if (y == NULL) 1597db96d56Sopenharmony_ci return error( 1607db96d56Sopenharmony_ci "unexpected NULL from PyNumber_Subtract"); 1617db96d56Sopenharmony_ci 1627db96d56Sopenharmony_ci out = F_PY_TO_S(y); 1637db96d56Sopenharmony_ci if (out != (TYPENAME)-1 || !PyErr_Occurred()) 1647db96d56Sopenharmony_ci return error( 1657db96d56Sopenharmony_ci "PyLong_AsXXX(-2**(NBITS-1)-1) didn't " 1667db96d56Sopenharmony_ci "complain"); 1677db96d56Sopenharmony_ci if (!PyErr_ExceptionMatches(PyExc_OverflowError)) 1687db96d56Sopenharmony_ci return error( 1697db96d56Sopenharmony_ci "PyLong_AsXXX(-2**(NBITS-1)-1) raised " 1707db96d56Sopenharmony_ci "something other than OverflowError"); 1717db96d56Sopenharmony_ci PyErr_Clear(); 1727db96d56Sopenharmony_ci UNBIND(y); 1737db96d56Sopenharmony_ci 1747db96d56Sopenharmony_ci Py_XDECREF(x); 1757db96d56Sopenharmony_ci Py_XDECREF(y); 1767db96d56Sopenharmony_ci Py_DECREF(one); 1777db96d56Sopenharmony_ci } 1787db96d56Sopenharmony_ci 1797db96d56Sopenharmony_ci /* Test F_PY_TO_{S,U} on non-pylong input. This should raise a TypeError. */ 1807db96d56Sopenharmony_ci { 1817db96d56Sopenharmony_ci TYPENAME out; 1827db96d56Sopenharmony_ci unsigned TYPENAME uout; 1837db96d56Sopenharmony_ci 1847db96d56Sopenharmony_ci Py_INCREF(Py_None); 1857db96d56Sopenharmony_ci 1867db96d56Sopenharmony_ci out = F_PY_TO_S(Py_None); 1877db96d56Sopenharmony_ci if (out != (TYPENAME)-1 || !PyErr_Occurred()) 1887db96d56Sopenharmony_ci return error("PyLong_AsXXX(None) didn't complain"); 1897db96d56Sopenharmony_ci if (!PyErr_ExceptionMatches(PyExc_TypeError)) 1907db96d56Sopenharmony_ci return error("PyLong_AsXXX(None) raised " 1917db96d56Sopenharmony_ci "something other than TypeError"); 1927db96d56Sopenharmony_ci PyErr_Clear(); 1937db96d56Sopenharmony_ci 1947db96d56Sopenharmony_ci uout = F_PY_TO_U(Py_None); 1957db96d56Sopenharmony_ci if (uout != (unsigned TYPENAME)-1 || !PyErr_Occurred()) 1967db96d56Sopenharmony_ci return error("PyLong_AsXXX(None) didn't complain"); 1977db96d56Sopenharmony_ci if (!PyErr_ExceptionMatches(PyExc_TypeError)) 1987db96d56Sopenharmony_ci return error("PyLong_AsXXX(None) raised " 1997db96d56Sopenharmony_ci "something other than TypeError"); 2007db96d56Sopenharmony_ci PyErr_Clear(); 2017db96d56Sopenharmony_ci 2027db96d56Sopenharmony_ci Py_DECREF(Py_None); 2037db96d56Sopenharmony_ci } 2047db96d56Sopenharmony_ci 2057db96d56Sopenharmony_ci Py_INCREF(Py_None); 2067db96d56Sopenharmony_ci return Py_None; 2077db96d56Sopenharmony_ci} 208