@@ -172,187 +172,100 @@ test_dict_iteration(PyObject* self, PyObject* args)
172172 return Py_None ;
173173}
174174
175- #ifdef HAVE_LONG_LONG
176175
177- /* Basic sanity checks for PyLong_{As, From}{Unsigned,}LongLong(). */
176+ /* Tests of PyLong_{As, From}{Unsigned,}Long(), and (#ifdef HAVE_LONG_LONG)
177+ PyLong_{As, From}{Unsigned,}LongLong()/
178+
179+ Note that the meat of the test is contained in testcapi_long.h.
180+ This is revolting, but delicate code duplication is worse: "almost
181+ exactly the same" code is needed to test LONG_LONG, but the ubiquitous
182+ dependence on type names makes it impossible to use a parameterized
183+ function. A giant macro would be even worse than this. A C++ template
184+ would be perfect.
185+
186+ The "report an error" functions are deliberately not part of the #include
187+ file: if the test fails, you can set a breakpoint in the appropriate
188+ error function directly, and crawl back from there in the debugger.
189+ */
190+
191+ #define UNBIND (X ) Py_DECREF(X); (X) = NULL
192+
193+ static PyObject *
194+ raise_test_long_error (const char * msg )
195+ {
196+ return raiseTestError ("test_long_api" , msg );
197+ }
198+
199+ #define TESTNAME test_long_api_inner
200+ #define TYPENAME long
201+ #define F_S_TO_PY PyLong_FromLong
202+ #define F_PY_TO_S PyLong_AsLong
203+ #define F_U_TO_PY PyLong_FromUnsignedLong
204+ #define F_PY_TO_U PyLong_AsUnsignedLong
205+ #define F_ERROR raise_test_long_error
206+
207+ #include "testcapi_long.h"
208+
209+ static PyObject *
210+ test_long_api (PyObject * self , PyObject * args )
211+ {
212+ if (!PyArg_ParseTuple (args , ":test_long_api" ))
213+ return NULL ;
214+
215+ return TESTNAME ();
216+ }
217+
218+ #undef TESTNAME
219+ #undef TYPENAME
220+ #undef F_S_TO_PY
221+ #undef F_PY_TO_S
222+ #undef F_U_TO_PY
223+ #undef F_PY_TO_U
224+ #undef F_ERROR
225+
226+ #ifdef HAVE_LONG_LONG
178227
179228static PyObject *
180229raise_test_longlong_error (const char * msg )
181230{
182231 return raiseTestError ("test_longlong_api" , msg );
183232}
184233
185- #define UNBIND (X ) Py_DECREF(X); (X) = NULL
234+ #define TESTNAME test_longlong_api_inner
235+ #define TYPENAME LONG_LONG
236+ #define F_S_TO_PY PyLong_FromLongLong
237+ #define F_PY_TO_S PyLong_AsLongLong
238+ #define F_U_TO_PY PyLong_FromUnsignedLongLong
239+ #define F_PY_TO_U PyLong_AsUnsignedLongLong
240+ #define F_ERROR raise_test_longlong_error
241+
242+ #include "testcapi_long.h"
186243
187244static PyObject *
188245test_longlong_api (PyObject * self , PyObject * args )
189246{
190- const int NBITS = SIZEOF_LONG_LONG * 8 ;
191- unsigned LONG_LONG base ;
192- PyObject * pyresult ;
193- int i ;
194-
195247 if (!PyArg_ParseTuple (args , ":test_longlong_api" ))
196248 return NULL ;
197249
250+ return TESTNAME ();
251+ }
198252
199- /* Note: This test lets PyObjects leak if an error is raised. Since
200- an error should never be raised, leaks are impossible <wink>. */
201-
202- /* Test native -> PyLong -> native roundtrip identity.
203- * Generate all powers of 2, and test them and their negations,
204- * plus the numbers +-1 off from them.
205- */
206- base = 1 ;
207- for (i = 0 ;
208- i < NBITS + 1 ; /* on last, base overflows to 0 */
209- ++ i , base <<= 1 )
210- {
211- int j ;
212- for (j = 0 ; j < 6 ; ++ j ) {
213- LONG_LONG in , out ;
214- unsigned LONG_LONG uin , uout ;
215-
216- /* For 0, 1, 2 use base; for 3, 4, 5 use -base */
217- uin = j < 3 ? base
218- : (unsigned LONG_LONG )(- (LONG_LONG )base );
219-
220- /* For 0 & 3, subtract 1.
221- * For 1 & 4, leave alone.
222- * For 2 & 5, add 1.
223- */
224- uin += (unsigned LONG_LONG )(LONG_LONG )(j % 3 - 1 );
225-
226- pyresult = PyLong_FromUnsignedLongLong (uin );
227- if (pyresult == NULL )
228- return raise_test_longlong_error (
229- "unsigned unexpected null result" );
230-
231- uout = PyLong_AsUnsignedLongLong (pyresult );
232- if (uout == (unsigned LONG_LONG )-1 && PyErr_Occurred ())
233- return raise_test_longlong_error (
234- "unsigned unexpected -1 result" );
235- if (uout != uin )
236- return raise_test_longlong_error (
237- "unsigned output != input" );
238- UNBIND (pyresult );
239-
240- in = (LONG_LONG )uin ;
241- pyresult = PyLong_FromLongLong (in );
242- if (pyresult == NULL )
243- return raise_test_longlong_error (
244- "signed unexpected null result" );
245-
246- out = PyLong_AsLongLong (pyresult );
247- if (out == (LONG_LONG )- 1 && PyErr_Occurred ())
248- return raise_test_longlong_error (
249- "signed unexpected -1 result" );
250- if (out != in )
251- return raise_test_longlong_error (
252- "signed output != input" );
253- UNBIND (pyresult );
254- }
255- }
256-
257- /* Overflow tests. The loop above ensured that all limit cases that
258- * should not overflow don't overflow, so all we need to do here is
259- * provoke one-over-the-limit cases (not exhaustive, but sharp).
260- */
261- {
262- PyObject * one , * x , * y ;
263- LONG_LONG out ;
264- unsigned LONG_LONG uout ;
265-
266- one = PyLong_FromLong (1 );
267- if (one == NULL )
268- return raise_test_longlong_error (
269- "unexpected NULL from PyLong_FromLong" );
270-
271- /* Unsigned complains about -1? */
272- x = PyNumber_Negative (one );
273- if (x == NULL )
274- return raise_test_longlong_error (
275- "unexpected NULL from PyNumber_Negative" );
276-
277- uout = PyLong_AsUnsignedLongLong (x );
278- if (uout != (unsigned LONG_LONG )-1 || !PyErr_Occurred ())
279- return raise_test_longlong_error (
280- "PyLong_AsUnsignedLongLong(-1) didn't "
281- "complain" );
282- PyErr_Clear ();
283- UNBIND (x );
284-
285- /* Unsigned complains about 2**NBITS? */
286- y = PyLong_FromLong ((long )NBITS );
287- if (y == NULL )
288- return raise_test_longlong_error (
289- "unexpected NULL from PyLong_FromLong" );
290-
291- x = PyNumber_Lshift (one , y ); /* 1L << NBITS, == 2**NBITS */
292- UNBIND (y );
293- if (x == NULL )
294- return raise_test_longlong_error (
295- "unexpected NULL from PyNumber_Lshift" );
296-
297- uout = PyLong_AsUnsignedLongLong (x );
298- if (uout != (unsigned LONG_LONG )-1 || !PyErr_Occurred ())
299- return raise_test_longlong_error (
300- "PyLong_AsUnsignedLongLong(2**NBITS) didn't "
301- "complain" );
302- PyErr_Clear ();
303-
304- /* Signed complains about 2**(NBITS-1)?
305- x still has 2**NBITS. */
306- y = PyNumber_Rshift (x , one ); /* 2**(NBITS-1) */
307- UNBIND (x );
308- if (y == NULL )
309- return raise_test_longlong_error (
310- "unexpected NULL from PyNumber_Rshift" );
311-
312- out = PyLong_AsLongLong (y );
313- if (out != (LONG_LONG )- 1 || !PyErr_Occurred ())
314- return raise_test_longlong_error (
315- "PyLong_AsLongLong(2**(NBITS-1)) didn't "
316- "complain" );
317- PyErr_Clear ();
318-
319- /* Signed complains about -2**(NBITS-1)-1?;
320- y still has 2**(NBITS-1). */
321- x = PyNumber_Negative (y ); /* -(2**(NBITS-1)) */
322- UNBIND (y );
323- if (x == NULL )
324- return raise_test_longlong_error (
325- "unexpected NULL from PyNumber_Negative" );
326-
327- y = PyNumber_Subtract (x , one ); /* -(2**(NBITS-1))-1 */
328- UNBIND (x );
329- if (y == NULL )
330- return raise_test_longlong_error (
331- "unexpected NULL from PyNumber_Subtract" );
332-
333- out = PyLong_AsLongLong (y );
334- if (out != (LONG_LONG )- 1 || !PyErr_Occurred ())
335- return raise_test_longlong_error (
336- "PyLong_AsLongLong(-2**(NBITS-1)-1) didn't "
337- "complain" );
338- PyErr_Clear ();
339- UNBIND (y );
340-
341- Py_XDECREF (x );
342- Py_XDECREF (y );
343- Py_DECREF (one );
344- }
253+ #undef TESTNAME
254+ #undef TYPENAME
255+ #undef F_S_TO_PY
256+ #undef F_PY_TO_S
257+ #undef F_U_TO_PY
258+ #undef F_PY_TO_U
259+ #undef F_ERROR
345260
346- Py_INCREF (Py_None );
347- return Py_None ;
348- }
261+ #endif /* ifdef HAVE_LONG_LONG */
349262
350- #endif
351263
352264static PyMethodDef TestMethods [] = {
353265 {"test_config" , test_config , METH_VARARGS },
354266 {"test_list_api" , test_list_api , METH_VARARGS },
355267 {"test_dict_iteration" , test_dict_iteration , METH_VARARGS },
268+ {"test_long_api" , test_long_api , METH_VARARGS },
356269#ifdef HAVE_LONG_LONG
357270 {"test_longlong_api" , test_longlong_api , METH_VARARGS },
358271#endif
0 commit comments