PageRenderTime 285ms CodeModel.GetById 181ms app.highlight 11ms RepoModel.GetById 90ms app.codeStats 0ms

/Modules/testcapi_long.h

http://unladen-swallow.googlecode.com/
C++ Header | 166 lines | 114 code | 23 blank | 29 comment | 42 complexity | 57e98f08856881640538798c7db66604 MD5 | raw file
  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
 10static PyObject *
 11TESTNAME(PyObject *error(const char*))
 12{
 13	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	base = 1;
 26	for (i = 0;
 27	     i < NBITS + 1;  /* on last, base overflows to 0 */
 28	     ++i, base <<= 1)
 29	{
 30		int j;
 31		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			uin = j < 3 ? base
 37				    : (unsigned TYPENAME)(-(TYPENAME)base);
 38
 39			/* For 0 & 3, subtract 1.
 40			 * For 1 & 4, leave alone.
 41			 * For 2 & 5, add 1.
 42			 */
 43			uin += (unsigned TYPENAME)(TYPENAME)(j % 3 - 1);
 44
 45			pyresult = F_U_TO_PY(uin);
 46			if (pyresult == NULL)
 47				return error(
 48				 "unsigned unexpected null result");
 49
 50			uout = F_PY_TO_U(pyresult);
 51			if (uout == (unsigned TYPENAME)-1 && PyErr_Occurred())
 52				return error(
 53					"unsigned unexpected -1 result");
 54			if (uout != uin)
 55				return error(
 56					"unsigned output != input");
 57			UNBIND(pyresult);
 58
 59			in = (TYPENAME)uin;
 60			pyresult = F_S_TO_PY(in);
 61			if (pyresult == NULL)
 62				return error(
 63					"signed unexpected null result");
 64
 65			out = F_PY_TO_S(pyresult);
 66			if (out == (TYPENAME)-1 && PyErr_Occurred())
 67				return error(
 68					"signed unexpected -1 result");
 69			if (out != in)
 70				return error(
 71					"signed output != input");
 72			UNBIND(pyresult);
 73		}
 74	}
 75
 76	/* Overflow tests.  The loop above ensured that all limit cases that
 77	 * should not overflow don't overflow, so all we need to do here is
 78	 * provoke one-over-the-limit cases (not exhaustive, but sharp).
 79	 */
 80	{
 81		PyObject *one, *x, *y;
 82		TYPENAME out;
 83		unsigned TYPENAME uout;
 84
 85		one = PyLong_FromLong(1);
 86		if (one == NULL)
 87			return error(
 88				"unexpected NULL from PyLong_FromLong");
 89
 90		/* Unsigned complains about -1? */
 91		x = PyNumber_Negative(one);
 92		if (x == NULL)
 93			return error(
 94				"unexpected NULL from PyNumber_Negative");
 95
 96		uout = F_PY_TO_U(x);
 97		if (uout != (unsigned TYPENAME)-1 || !PyErr_Occurred())
 98			return error(
 99				"PyLong_AsUnsignedXXX(-1) didn't complain");
100		PyErr_Clear();
101		UNBIND(x);
102
103		/* Unsigned complains about 2**NBITS? */
104		y = PyLong_FromLong((long)NBITS);
105		if (y == NULL)
106			return error(
107				"unexpected NULL from PyLong_FromLong");
108
109		x = PyNumber_Lshift(one, y); /* 1L << NBITS, == 2**NBITS */
110		UNBIND(y);
111		if (x == NULL)
112			return error(
113				"unexpected NULL from PyNumber_Lshift");
114
115  		uout = F_PY_TO_U(x);
116		if (uout != (unsigned TYPENAME)-1 || !PyErr_Occurred())
117			return error(
118				"PyLong_AsUnsignedXXX(2**NBITS) didn't "
119				"complain");
120		PyErr_Clear();
121
122		/* Signed complains about 2**(NBITS-1)?
123		   x still has 2**NBITS. */
124		y = PyNumber_Rshift(x, one); /* 2**(NBITS-1) */
125		UNBIND(x);
126		if (y == NULL)
127			return error(
128				"unexpected NULL from PyNumber_Rshift");
129
130		out = F_PY_TO_S(y);
131		if (out != (TYPENAME)-1 || !PyErr_Occurred())
132			return error(
133				"PyLong_AsXXX(2**(NBITS-1)) didn't "
134				"complain");
135		PyErr_Clear();
136
137		/* Signed complains about -2**(NBITS-1)-1?;
138		   y still has 2**(NBITS-1). */
139		x = PyNumber_Negative(y);  /* -(2**(NBITS-1)) */
140		UNBIND(y);
141		if (x == NULL)
142			return error(
143				"unexpected NULL from PyNumber_Negative");
144
145		y = PyNumber_Subtract(x, one); /* -(2**(NBITS-1))-1 */
146		UNBIND(x);
147		if (y == NULL)
148			return error(
149				"unexpected NULL from PyNumber_Subtract");
150
151		out = F_PY_TO_S(y);
152		if (out != (TYPENAME)-1 || !PyErr_Occurred())
153			return error(
154				"PyLong_AsXXX(-2**(NBITS-1)-1) didn't "
155				"complain");
156		PyErr_Clear();
157		UNBIND(y);
158
159		Py_XDECREF(x);
160		Py_XDECREF(y);
161		Py_DECREF(one);
162	}
163
164	Py_INCREF(Py_None);
165	return Py_None;
166}