| #include "parts.h" |
| |
| |
| static PyObject * |
| raiseTestError(const char* test_name, const char* msg) |
| { |
| PyErr_Format(PyExc_AssertionError, "%s: %s", test_name, msg); |
| return NULL; |
| } |
| |
| /* Tests of PyLong_{As, From}{Unsigned,}Long(), and |
| PyLong_{As, From}{Unsigned,}LongLong(). |
| |
| Note that the meat of the test is contained in testcapi_long.h. |
| This is revolting, but delicate code duplication is worse: "almost |
| exactly the same" code is needed to test long long, but the ubiquitous |
| dependence on type names makes it impossible to use a parameterized |
| function. A giant macro would be even worse than this. A C++ template |
| would be perfect. |
| |
| The "report an error" functions are deliberately not part of the #include |
| file: if the test fails, you can set a breakpoint in the appropriate |
| error function directly, and crawl back from there in the debugger. |
| */ |
| |
| #define UNBIND(X) Py_DECREF(X); (X) = NULL |
| |
| static PyObject * |
| raise_test_long_error(const char* msg) |
| { |
| return raiseTestError("test_long_api", msg); |
| } |
| |
| #define TESTNAME test_long_api_inner |
| #define TYPENAME long |
| #define F_S_TO_PY PyLong_FromLong |
| #define F_PY_TO_S PyLong_AsLong |
| #define F_U_TO_PY PyLong_FromUnsignedLong |
| #define F_PY_TO_U PyLong_AsUnsignedLong |
| |
| #include "testcapi_long.h" |
| |
| static PyObject * |
| test_long_api(PyObject* self, PyObject *Py_UNUSED(ignored)) |
| { |
| return TESTNAME(raise_test_long_error); |
| } |
| |
| #undef TESTNAME |
| #undef TYPENAME |
| #undef F_S_TO_PY |
| #undef F_PY_TO_S |
| #undef F_U_TO_PY |
| #undef F_PY_TO_U |
| |
| static PyObject * |
| raise_test_longlong_error(const char* msg) |
| { |
| return raiseTestError("test_longlong_api", msg); |
| } |
| |
| #define TESTNAME test_longlong_api_inner |
| #define TYPENAME long long |
| #define F_S_TO_PY PyLong_FromLongLong |
| #define F_PY_TO_S PyLong_AsLongLong |
| #define F_U_TO_PY PyLong_FromUnsignedLongLong |
| #define F_PY_TO_U PyLong_AsUnsignedLongLong |
| |
| #include "testcapi_long.h" |
| |
| static PyObject * |
| test_longlong_api(PyObject* self, PyObject *args) |
| { |
| return TESTNAME(raise_test_longlong_error); |
| } |
| |
| #undef TESTNAME |
| #undef TYPENAME |
| #undef F_S_TO_PY |
| #undef F_PY_TO_S |
| #undef F_U_TO_PY |
| #undef F_PY_TO_U |
| |
| /* Test the PyLong_AsLongAndOverflow API. General conversion to PY_LONG |
| is tested by test_long_api_inner. This test will concentrate on proper |
| handling of overflow. |
| */ |
| |
| static PyObject * |
| test_long_and_overflow(PyObject *self, PyObject *Py_UNUSED(ignored)) |
| { |
| PyObject *num, *one, *temp; |
| long value; |
| int overflow; |
| |
| /* Test that overflow is set properly for a large value. */ |
| /* num is a number larger than LONG_MAX even on 64-bit platforms */ |
| num = PyLong_FromString("FFFFFFFFFFFFFFFFFFFFFFFF", NULL, 16); |
| if (num == NULL) |
| return NULL; |
| overflow = 1234; |
| value = PyLong_AsLongAndOverflow(num, &overflow); |
| Py_DECREF(num); |
| if (value == -1 && PyErr_Occurred()) |
| return NULL; |
| if (value != -1) |
| return raiseTestError("test_long_and_overflow", |
| "return value was not set to -1"); |
| if (overflow != 1) |
| return raiseTestError("test_long_and_overflow", |
| "overflow was not set to 1"); |
| |
| /* Same again, with num = LONG_MAX + 1 */ |
| num = PyLong_FromLong(LONG_MAX); |
| if (num == NULL) |
| return NULL; |
| one = PyLong_FromLong(1L); |
| if (one == NULL) { |
| Py_DECREF(num); |
| return NULL; |
| } |
| temp = PyNumber_Add(num, one); |
| Py_DECREF(one); |
| Py_SETREF(num, temp); |
| if (num == NULL) |
| return NULL; |
| overflow = 0; |
| value = PyLong_AsLongAndOverflow(num, &overflow); |
| Py_DECREF(num); |
| if (value == -1 && PyErr_Occurred()) |
| return NULL; |
| if (value != -1) |
| return raiseTestError("test_long_and_overflow", |
| "return value was not set to -1"); |
| if (overflow != 1) |
| return raiseTestError("test_long_and_overflow", |
| "overflow was not set to 1"); |
| |
| /* Test that overflow is set properly for a large negative value. */ |
| /* num is a number smaller than LONG_MIN even on 64-bit platforms */ |
| num = PyLong_FromString("-FFFFFFFFFFFFFFFFFFFFFFFF", NULL, 16); |
| if (num == NULL) |
| return NULL; |
| overflow = 1234; |
| value = PyLong_AsLongAndOverflow(num, &overflow); |
| Py_DECREF(num); |
| if (value == -1 && PyErr_Occurred()) |
| return NULL; |
| if (value != -1) |
| return raiseTestError("test_long_and_overflow", |
| "return value was not set to -1"); |
| if (overflow != -1) |
| return raiseTestError("test_long_and_overflow", |
| "overflow was not set to -1"); |
| |
| /* Same again, with num = LONG_MIN - 1 */ |
| num = PyLong_FromLong(LONG_MIN); |
| if (num == NULL) |
| return NULL; |
| one = PyLong_FromLong(1L); |
| if (one == NULL) { |
| Py_DECREF(num); |
| return NULL; |
| } |
| temp = PyNumber_Subtract(num, one); |
| Py_DECREF(one); |
| Py_SETREF(num, temp); |
| if (num == NULL) |
| return NULL; |
| overflow = 0; |
| value = PyLong_AsLongAndOverflow(num, &overflow); |
| Py_DECREF(num); |
| if (value == -1 && PyErr_Occurred()) |
| return NULL; |
| if (value != -1) |
| return raiseTestError("test_long_and_overflow", |
| "return value was not set to -1"); |
| if (overflow != -1) |
| return raiseTestError("test_long_and_overflow", |
| "overflow was not set to -1"); |
| |
| /* Test that overflow is cleared properly for small values. */ |
| num = PyLong_FromString("FF", NULL, 16); |
| if (num == NULL) |
| return NULL; |
| overflow = 1234; |
| value = PyLong_AsLongAndOverflow(num, &overflow); |
| Py_DECREF(num); |
| if (value == -1 && PyErr_Occurred()) |
| return NULL; |
| if (value != 0xFF) |
| return raiseTestError("test_long_and_overflow", |
| "expected return value 0xFF"); |
| if (overflow != 0) |
| return raiseTestError("test_long_and_overflow", |
| "overflow was not cleared"); |
| |
| num = PyLong_FromString("-FF", NULL, 16); |
| if (num == NULL) |
| return NULL; |
| overflow = 0; |
| value = PyLong_AsLongAndOverflow(num, &overflow); |
| Py_DECREF(num); |
| if (value == -1 && PyErr_Occurred()) |
| return NULL; |
| if (value != -0xFF) |
| return raiseTestError("test_long_and_overflow", |
| "expected return value 0xFF"); |
| if (overflow != 0) |
| return raiseTestError("test_long_and_overflow", |
| "overflow was set incorrectly"); |
| |
| num = PyLong_FromLong(LONG_MAX); |
| if (num == NULL) |
| return NULL; |
| overflow = 1234; |
| value = PyLong_AsLongAndOverflow(num, &overflow); |
| Py_DECREF(num); |
| if (value == -1 && PyErr_Occurred()) |
| return NULL; |
| if (value != LONG_MAX) |
| return raiseTestError("test_long_and_overflow", |
| "expected return value LONG_MAX"); |
| if (overflow != 0) |
| return raiseTestError("test_long_and_overflow", |
| "overflow was not cleared"); |
| |
| num = PyLong_FromLong(LONG_MIN); |
| if (num == NULL) |
| return NULL; |
| overflow = 0; |
| value = PyLong_AsLongAndOverflow(num, &overflow); |
| Py_DECREF(num); |
| if (value == -1 && PyErr_Occurred()) |
| return NULL; |
| if (value != LONG_MIN) |
| return raiseTestError("test_long_and_overflow", |
| "expected return value LONG_MIN"); |
| if (overflow != 0) |
| return raiseTestError("test_long_and_overflow", |
| "overflow was not cleared"); |
| |
| Py_RETURN_NONE; |
| } |
| |
| /* Test the PyLong_AsLongLongAndOverflow API. General conversion to |
| long long is tested by test_long_api_inner. This test will |
| concentrate on proper handling of overflow. |
| */ |
| |
| static PyObject * |
| test_long_long_and_overflow(PyObject *self, PyObject *Py_UNUSED(ignored)) |
| { |
| PyObject *num, *one, *temp; |
| long long value; |
| int overflow; |
| |
| /* Test that overflow is set properly for a large value. */ |
| /* num is a number larger than LLONG_MAX on a typical machine. */ |
| num = PyLong_FromString("FFFFFFFFFFFFFFFFFFFFFFFF", NULL, 16); |
| if (num == NULL) |
| return NULL; |
| overflow = 1234; |
| value = PyLong_AsLongLongAndOverflow(num, &overflow); |
| Py_DECREF(num); |
| if (value == -1 && PyErr_Occurred()) |
| return NULL; |
| if (value != -1) |
| return raiseTestError("test_long_long_and_overflow", |
| "return value was not set to -1"); |
| if (overflow != 1) |
| return raiseTestError("test_long_long_and_overflow", |
| "overflow was not set to 1"); |
| |
| /* Same again, with num = LLONG_MAX + 1 */ |
| num = PyLong_FromLongLong(LLONG_MAX); |
| if (num == NULL) |
| return NULL; |
| one = PyLong_FromLong(1L); |
| if (one == NULL) { |
| Py_DECREF(num); |
| return NULL; |
| } |
| temp = PyNumber_Add(num, one); |
| Py_DECREF(one); |
| Py_SETREF(num, temp); |
| if (num == NULL) |
| return NULL; |
| overflow = 0; |
| value = PyLong_AsLongLongAndOverflow(num, &overflow); |
| Py_DECREF(num); |
| if (value == -1 && PyErr_Occurred()) |
| return NULL; |
| if (value != -1) |
| return raiseTestError("test_long_long_and_overflow", |
| "return value was not set to -1"); |
| if (overflow != 1) |
| return raiseTestError("test_long_long_and_overflow", |
| "overflow was not set to 1"); |
| |
| /* Test that overflow is set properly for a large negative value. */ |
| /* num is a number smaller than LLONG_MIN on a typical platform */ |
| num = PyLong_FromString("-FFFFFFFFFFFFFFFFFFFFFFFF", NULL, 16); |
| if (num == NULL) |
| return NULL; |
| overflow = 1234; |
| value = PyLong_AsLongLongAndOverflow(num, &overflow); |
| Py_DECREF(num); |
| if (value == -1 && PyErr_Occurred()) |
| return NULL; |
| if (value != -1) |
| return raiseTestError("test_long_long_and_overflow", |
| "return value was not set to -1"); |
| if (overflow != -1) |
| return raiseTestError("test_long_long_and_overflow", |
| "overflow was not set to -1"); |
| |
| /* Same again, with num = LLONG_MIN - 1 */ |
| num = PyLong_FromLongLong(LLONG_MIN); |
| if (num == NULL) |
| return NULL; |
| one = PyLong_FromLong(1L); |
| if (one == NULL) { |
| Py_DECREF(num); |
| return NULL; |
| } |
| temp = PyNumber_Subtract(num, one); |
| Py_DECREF(one); |
| Py_SETREF(num, temp); |
| if (num == NULL) |
| return NULL; |
| overflow = 0; |
| value = PyLong_AsLongLongAndOverflow(num, &overflow); |
| Py_DECREF(num); |
| if (value == -1 && PyErr_Occurred()) |
| return NULL; |
| if (value != -1) |
| return raiseTestError("test_long_long_and_overflow", |
| "return value was not set to -1"); |
| if (overflow != -1) |
| return raiseTestError("test_long_long_and_overflow", |
| "overflow was not set to -1"); |
| |
| /* Test that overflow is cleared properly for small values. */ |
| num = PyLong_FromString("FF", NULL, 16); |
| if (num == NULL) |
| return NULL; |
| overflow = 1234; |
| value = PyLong_AsLongLongAndOverflow(num, &overflow); |
| Py_DECREF(num); |
| if (value == -1 && PyErr_Occurred()) |
| return NULL; |
| if (value != 0xFF) |
| return raiseTestError("test_long_long_and_overflow", |
| "expected return value 0xFF"); |
| if (overflow != 0) |
| return raiseTestError("test_long_long_and_overflow", |
| "overflow was not cleared"); |
| |
| num = PyLong_FromString("-FF", NULL, 16); |
| if (num == NULL) |
| return NULL; |
| overflow = 0; |
| value = PyLong_AsLongLongAndOverflow(num, &overflow); |
| Py_DECREF(num); |
| if (value == -1 && PyErr_Occurred()) |
| return NULL; |
| if (value != -0xFF) |
| return raiseTestError("test_long_long_and_overflow", |
| "expected return value 0xFF"); |
| if (overflow != 0) |
| return raiseTestError("test_long_long_and_overflow", |
| "overflow was set incorrectly"); |
| |
| num = PyLong_FromLongLong(LLONG_MAX); |
| if (num == NULL) |
| return NULL; |
| overflow = 1234; |
| value = PyLong_AsLongLongAndOverflow(num, &overflow); |
| Py_DECREF(num); |
| if (value == -1 && PyErr_Occurred()) |
| return NULL; |
| if (value != LLONG_MAX) |
| return raiseTestError("test_long_long_and_overflow", |
| "expected return value LLONG_MAX"); |
| if (overflow != 0) |
| return raiseTestError("test_long_long_and_overflow", |
| "overflow was not cleared"); |
| |
| num = PyLong_FromLongLong(LLONG_MIN); |
| if (num == NULL) |
| return NULL; |
| overflow = 0; |
| value = PyLong_AsLongLongAndOverflow(num, &overflow); |
| Py_DECREF(num); |
| if (value == -1 && PyErr_Occurred()) |
| return NULL; |
| if (value != LLONG_MIN) |
| return raiseTestError("test_long_long_and_overflow", |
| "expected return value LLONG_MIN"); |
| if (overflow != 0) |
| return raiseTestError("test_long_long_and_overflow", |
| "overflow was not cleared"); |
| |
| Py_RETURN_NONE; |
| } |
| |
| /* Test the PyLong_As{Size,Ssize}_t API. At present this just tests that |
| non-integer arguments are handled correctly. It should be extended to |
| test overflow handling. |
| */ |
| |
| static PyObject * |
| test_long_as_size_t(PyObject *self, PyObject *Py_UNUSED(ignored)) |
| { |
| size_t out_u; |
| Py_ssize_t out_s; |
| |
| Py_INCREF(Py_None); |
| |
| out_u = PyLong_AsSize_t(Py_None); |
| if (out_u != (size_t)-1 || !PyErr_Occurred()) |
| return raiseTestError("test_long_as_size_t", |
| "PyLong_AsSize_t(None) didn't complain"); |
| if (!PyErr_ExceptionMatches(PyExc_TypeError)) |
| return raiseTestError("test_long_as_size_t", |
| "PyLong_AsSize_t(None) raised " |
| "something other than TypeError"); |
| PyErr_Clear(); |
| |
| out_s = PyLong_AsSsize_t(Py_None); |
| if (out_s != (Py_ssize_t)-1 || !PyErr_Occurred()) |
| return raiseTestError("test_long_as_size_t", |
| "PyLong_AsSsize_t(None) didn't complain"); |
| if (!PyErr_ExceptionMatches(PyExc_TypeError)) |
| return raiseTestError("test_long_as_size_t", |
| "PyLong_AsSsize_t(None) raised " |
| "something other than TypeError"); |
| PyErr_Clear(); |
| |
| /* Py_INCREF(Py_None) omitted - we already have a reference to it. */ |
| return Py_None; |
| } |
| |
| static PyObject * |
| test_long_as_unsigned_long_long_mask(PyObject *self, |
| PyObject *Py_UNUSED(ignored)) |
| { |
| unsigned long long res = PyLong_AsUnsignedLongLongMask(NULL); |
| |
| if (res != (unsigned long long)-1 || !PyErr_Occurred()) { |
| return raiseTestError("test_long_as_unsigned_long_long_mask", |
| "PyLong_AsUnsignedLongLongMask(NULL) didn't " |
| "complain"); |
| } |
| if (!PyErr_ExceptionMatches(PyExc_SystemError)) { |
| return raiseTestError("test_long_as_unsigned_long_long_mask", |
| "PyLong_AsUnsignedLongLongMask(NULL) raised " |
| "something other than SystemError"); |
| } |
| PyErr_Clear(); |
| Py_RETURN_NONE; |
| } |
| |
| /* Test the PyLong_AsDouble API. At present this just tests that |
| non-integer arguments are handled correctly. |
| */ |
| |
| static PyObject * |
| test_long_as_double(PyObject *self, PyObject *Py_UNUSED(ignored)) |
| { |
| double out; |
| |
| Py_INCREF(Py_None); |
| |
| out = PyLong_AsDouble(Py_None); |
| if (out != -1.0 || !PyErr_Occurred()) |
| return raiseTestError("test_long_as_double", |
| "PyLong_AsDouble(None) didn't complain"); |
| if (!PyErr_ExceptionMatches(PyExc_TypeError)) |
| return raiseTestError("test_long_as_double", |
| "PyLong_AsDouble(None) raised " |
| "something other than TypeError"); |
| PyErr_Clear(); |
| |
| /* Py_INCREF(Py_None) omitted - we already have a reference to it. */ |
| return Py_None; |
| } |
| |
| /* Simple test of _PyLong_NumBits and _PyLong_Sign. */ |
| static PyObject * |
| test_long_numbits(PyObject *self, PyObject *Py_UNUSED(ignored)) |
| { |
| struct triple { |
| long input; |
| size_t nbits; |
| int sign; |
| } testcases[] = {{0, 0, 0}, |
| {1L, 1, 1}, |
| {-1L, 1, -1}, |
| {2L, 2, 1}, |
| {-2L, 2, -1}, |
| {3L, 2, 1}, |
| {-3L, 2, -1}, |
| {4L, 3, 1}, |
| {-4L, 3, -1}, |
| {0x7fffL, 15, 1}, /* one Python int digit */ |
| {-0x7fffL, 15, -1}, |
| {0xffffL, 16, 1}, |
| {-0xffffL, 16, -1}, |
| {0xfffffffL, 28, 1}, |
| {-0xfffffffL, 28, -1}}; |
| size_t i; |
| |
| for (i = 0; i < Py_ARRAY_LENGTH(testcases); ++i) { |
| size_t nbits; |
| int sign; |
| PyObject *plong; |
| |
| plong = PyLong_FromLong(testcases[i].input); |
| if (plong == NULL) |
| return NULL; |
| nbits = _PyLong_NumBits(plong); |
| sign = _PyLong_Sign(plong); |
| |
| Py_DECREF(plong); |
| if (nbits != testcases[i].nbits) |
| return raiseTestError("test_long_numbits", |
| "wrong result for _PyLong_NumBits"); |
| if (sign != testcases[i].sign) |
| return raiseTestError("test_long_numbits", |
| "wrong result for _PyLong_Sign"); |
| } |
| Py_RETURN_NONE; |
| } |
| |
| static PyMethodDef test_methods[] = { |
| {"test_long_and_overflow", test_long_and_overflow, METH_NOARGS}, |
| {"test_long_api", test_long_api, METH_NOARGS}, |
| {"test_long_as_double", test_long_as_double, METH_NOARGS}, |
| {"test_long_as_size_t", test_long_as_size_t, METH_NOARGS}, |
| {"test_long_as_unsigned_long_long_mask", test_long_as_unsigned_long_long_mask, METH_NOARGS}, |
| {"test_long_long_and_overflow",test_long_long_and_overflow, METH_NOARGS}, |
| {"test_long_numbits", test_long_numbits, METH_NOARGS}, |
| {"test_longlong_api", test_longlong_api, METH_NOARGS}, |
| {NULL}, |
| }; |
| |
| int |
| _PyTestCapi_Init_Long(PyObject *mod) |
| { |
| if (PyModule_AddFunctions(mod, test_methods) < 0) { |
| return -1; |
| } |
| |
| return 0; |
| } |