[Python-checkins] CVS: python/dist/src/Modules _testcapimodule.c,1.4,1.5

Tim Peters tim_one@users.sourceforge.net
Tue, 12 Jun 2001 17:36:00 -0700


Update of /cvsroot/python/python/dist/src/Modules
In directory usw-pr-cvs1:/tmp/cvs-serv10010/python/dist/src/Modules

Modified Files:
	_testcapimodule.c 
Log Message:
longobject.c:
    Replaced PyLong_{As,From}{Unsigned,}LongLong guts with calls
    to _PyLong_{As,From}ByteArray.
_testcapimodule.c:
    Added strong tests of PyLong_{As,From}{Unsigned,}LongLong.

Fixes SF bug #432552 PyLong_AsLongLong() problems.
Possible bugfix candidate, but the fix relies on code added to longobject
to support the new q/Q structmodule format codes.


Index: _testcapimodule.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/_testcapimodule.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -r1.4 -r1.5
*** _testcapimodule.c	2001/06/12 20:10:01	1.4
--- _testcapimodule.c	2001/06/13 00:35:57	1.5
***************
*** 178,203 ****
  
  static PyObject *
  test_longlong_api(PyObject* self, PyObject* args)
  {
! 	/* unsigned LONG_LONG uinput, uoutput; */
! 	LONG_LONG input, output;
  	PyObject *pyresult;
  
          if (!PyArg_ParseTuple(args, ":test_longlong_api"))
                  return NULL;
  
! 	input = 0;
! 	pyresult = PyLong_FromLongLong(input);
! 	if (pyresult == NULL)
! 		return raiseTestError("test_longlong_api",
! 				      "unexpected null result");
! 	output = PyLong_AsLongLong(pyresult);
! 	if (output == (LONG_LONG)-1 && PyErr_Occurred())
! 		return raiseTestError("test_longlong_api",
! 				      "unexpected -1 result");
! 	if (output != input)
! 		return raiseTestError("test_longlong_api",
! 				       "output != input");
! 	Py_DECREF(pyresult);
  
  	Py_INCREF(Py_None);
--- 178,346 ----
  
  static PyObject *
+ raise_test_longlong_error(const char* msg)
+ {
+ 	return raiseTestError("test_longlong_api", msg);
+ }
+ 
+ #define UNBIND(X)  Py_DECREF(X); (X) = NULL
+ 
+ static PyObject *
  test_longlong_api(PyObject* self, PyObject* args)
  {
! 	const int NBITS = SIZEOF_LONG_LONG * 8;
! 	unsigned LONG_LONG base;
  	PyObject *pyresult;
+ 	int i;
  
          if (!PyArg_ParseTuple(args, ":test_longlong_api"))
                  return NULL;
+ 
+ 
+ 	/* 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) {
+ 			LONG_LONG in, out;
+ 			unsigned LONG_LONG uin, uout;
+ 
+ 			/* For 0, 1, 2 use base; for 3, 4, 5 use -base */
+ 			uin = j < 3 ? base
+ 				    : (unsigned LONG_LONG)(-(LONG_LONG)base);
+ 
+ 			/* For 0 & 3, subtract 1.
+ 			 * For 1 & 4, leave alone.
+ 			 * For 2 & 5, add 1.
+ 			 */
+ 			uin += (unsigned LONG_LONG)(LONG_LONG)(j % 3 - 1);
+ 
+ 			pyresult = PyLong_FromUnsignedLongLong(uin);
+ 			if (pyresult == NULL)
+ 				return raise_test_longlong_error(
+ 					"unsigned unexpected null result");
+ 
+ 			uout = PyLong_AsUnsignedLongLong(pyresult);
+ 			if (uout == (unsigned LONG_LONG)-1 && PyErr_Occurred())
+ 				return raise_test_longlong_error(
+ 					"unsigned unexpected -1 result");
+ 			if (uout != uin)
+ 				return raise_test_longlong_error(
+ 					"unsigned output != input");
+ 			UNBIND(pyresult);
+ 
+ 			in = (LONG_LONG)uin;
+ 			pyresult = PyLong_FromLongLong(in);
+ 			if (pyresult == NULL)
+ 				return raise_test_longlong_error(
+ 					"signed unexpected null result");
+ 
+ 			out = PyLong_AsLongLong(pyresult);
+ 			if (out == (LONG_LONG)-1 && PyErr_Occurred())
+ 				return raise_test_longlong_error(
+ 					"signed unexpected -1 result");
+ 			if (out != in)
+ 				return raise_test_longlong_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;
+ 		LONG_LONG out;
+ 		unsigned LONG_LONG uout;
+ 
+ 		one = PyLong_FromLong(1);
+ 		if (one == NULL)
+ 			return raise_test_longlong_error(
+ 				"unexpected NULL from PyLong_FromLong");
+ 
+ 		/* Unsigned complains about -1? */
+ 		x = PyNumber_Negative(one);
+ 		if (x == NULL)
+ 			return raise_test_longlong_error(
+ 				"unexpected NULL from PyNumber_Negative");
+ 
+ 		uout = PyLong_AsUnsignedLongLong(x);
+ 		if (uout != (unsigned LONG_LONG)-1 || !PyErr_Occurred())
+ 			return raise_test_longlong_error(
+ 				"PyLong_AsUnsignedLongLong(-1) didn't "
+ 				"complain");
+ 		PyErr_Clear();
+ 		UNBIND(x);
+ 
+ 		/* Unsigned complains about 2**NBITS? */
+ 		y = PyLong_FromLong((long)NBITS);
+ 		if (y == NULL)
+ 			return raise_test_longlong_error(
+ 				"unexpected NULL from PyLong_FromLong");
+ 
+ 		x = PyNumber_Lshift(one, y); /* 1L << NBITS, == 2**NBITS */
+ 		UNBIND(y);
+ 		if (x == NULL)
+ 			return raise_test_longlong_error(
+ 				"unexpected NULL from PyNumber_Lshift");
+ 
+   		uout = PyLong_AsUnsignedLongLong(x);
+ 		if (uout != (unsigned LONG_LONG)-1 || !PyErr_Occurred())
+ 			return raise_test_longlong_error(
+ 				"PyLong_AsUnsignedLongLong(2**NBITS) didn't "
+ 				"complain");
+ 		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 raise_test_longlong_error(
+ 				"unexpected NULL from PyNumber_Rshift");
+ 
+ 		out = PyLong_AsLongLong(y);
+ 		if (out != (LONG_LONG)-1 || !PyErr_Occurred())
+ 			return raise_test_longlong_error(
+ 				"PyLong_AsLongLong(2**(NBITS-1)) didn't "
+ 				"complain");
+ 		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 raise_test_longlong_error(
+ 				"unexpected NULL from PyNumber_Negative");
+ 
+ 		y = PyNumber_Subtract(x, one); /* -(2**(NBITS-1))-1 */
+ 		UNBIND(x);
+ 		if (y == NULL)
+ 			return raise_test_longlong_error(
+ 				"unexpected NULL from PyNumber_Subtract");
+ 
+ 		out = PyLong_AsLongLong(y);
+ 		if (out != (LONG_LONG)-1 || !PyErr_Occurred())
+ 			return raise_test_longlong_error(
+ 				"PyLong_AsLongLong(-2**(NBITS-1)-1) didn't "
+ 				"complain");
+ 		PyErr_Clear();
+ 		UNBIND(y);
  
! 		Py_XDECREF(x);
! 		Py_XDECREF(y);
! 		Py_DECREF(one);
! 	}
  
  	Py_INCREF(Py_None);