blob: 7c5a7e7795823fab32052b666bb1d6f1618376c6 [file] [log] [blame]
Tim Peterse7c1f9b2001-06-14 00:55:41 +00001/* 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* -> TypeError
8 F_ERROR error-report function; char* -> PyObject* (returns NULL)
9*/
10
11static PyObject *
12TESTNAME()
13{
14 const int NBITS = sizeof(TYPENAME) * 8;
15 unsigned TYPENAME base;
16 PyObject *pyresult;
17 int i;
18
19 /* Note: This test lets PyObjects leak if an error is raised. Since
20 an error should never be raised, leaks are impossible <wink>. */
21
22 /* Test native -> PyLong -> native roundtrip identity.
23 * Generate all powers of 2, and test them and their negations,
24 * plus the numbers +-1 off from them.
25 */
26 base = 1;
27 for (i = 0;
28 i < NBITS + 1; /* on last, base overflows to 0 */
29 ++i, base <<= 1)
30 {
31 int j;
32 for (j = 0; j < 6; ++j) {
33 TYPENAME in, out;
34 unsigned TYPENAME uin, uout;
35
36 /* For 0, 1, 2 use base; for 3, 4, 5 use -base */
37 uin = j < 3 ? base
38 : (unsigned TYPENAME)(-(TYPENAME)base);
39
40 /* For 0 & 3, subtract 1.
41 * For 1 & 4, leave alone.
42 * For 2 & 5, add 1.
43 */
44 uin += (unsigned TYPENAME)(TYPENAME)(j % 3 - 1);
45
46 pyresult = F_U_TO_PY(uin);
47 if (pyresult == NULL)
48 return F_ERROR(
49 "unsigned unexpected null result");
50
51 uout = F_PY_TO_U(pyresult);
52 if (uout == (unsigned TYPENAME)-1 && PyErr_Occurred())
53 return F_ERROR(
54 "unsigned unexpected -1 result");
55 if (uout != uin)
56 return F_ERROR(
57 "unsigned output != input");
58 UNBIND(pyresult);
59
60 in = (TYPENAME)uin;
61 pyresult = F_S_TO_PY(in);
62 if (pyresult == NULL)
63 return F_ERROR(
64 "signed unexpected null result");
65
66 out = F_PY_TO_S(pyresult);
67 if (out == (TYPENAME)-1 && PyErr_Occurred())
68 return F_ERROR(
69 "signed unexpected -1 result");
70 if (out != in)
71 return F_ERROR(
72 "signed output != input");
73 UNBIND(pyresult);
74 }
75 }
76
77 /* Overflow tests. The loop above ensured that all limit cases that
78 * should not overflow don't overflow, so all we need to do here is
79 * provoke one-over-the-limit cases (not exhaustive, but sharp).
80 */
81 {
82 PyObject *one, *x, *y;
83 TYPENAME out;
84 unsigned TYPENAME uout;
85
86 one = PyLong_FromLong(1);
87 if (one == NULL)
88 return F_ERROR(
89 "unexpected NULL from PyLong_FromLong");
90
91 /* Unsigned complains about -1? */
92 x = PyNumber_Negative(one);
93 if (x == NULL)
94 return F_ERROR(
95 "unexpected NULL from PyNumber_Negative");
96
97 uout = F_PY_TO_U(x);
98 if (uout != (unsigned TYPENAME)-1 || !PyErr_Occurred())
99 return F_ERROR(
100 "PyLong_AsUnsignedXXX(-1) didn't complain");
101 PyErr_Clear();
102 UNBIND(x);
103
104 /* Unsigned complains about 2**NBITS? */
105 y = PyLong_FromLong((long)NBITS);
106 if (y == NULL)
107 return F_ERROR(
108 "unexpected NULL from PyLong_FromLong");
109
110 x = PyNumber_Lshift(one, y); /* 1L << NBITS, == 2**NBITS */
111 UNBIND(y);
112 if (x == NULL)
113 return F_ERROR(
114 "unexpected NULL from PyNumber_Lshift");
115
116 uout = F_PY_TO_U(x);
117 if (uout != (unsigned TYPENAME)-1 || !PyErr_Occurred())
118 return F_ERROR(
119 "PyLong_AsUnsignedXXX(2**NBITS) didn't "
120 "complain");
121 PyErr_Clear();
122
123 /* Signed complains about 2**(NBITS-1)?
124 x still has 2**NBITS. */
125 y = PyNumber_Rshift(x, one); /* 2**(NBITS-1) */
126 UNBIND(x);
127 if (y == NULL)
128 return F_ERROR(
129 "unexpected NULL from PyNumber_Rshift");
130
131 out = F_PY_TO_S(y);
132 if (out != (TYPENAME)-1 || !PyErr_Occurred())
133 return F_ERROR(
134 "PyLong_AsXXX(2**(NBITS-1)) didn't "
135 "complain");
136 PyErr_Clear();
137
138 /* Signed complains about -2**(NBITS-1)-1?;
139 y still has 2**(NBITS-1). */
140 x = PyNumber_Negative(y); /* -(2**(NBITS-1)) */
141 UNBIND(y);
142 if (x == NULL)
143 return F_ERROR(
144 "unexpected NULL from PyNumber_Negative");
145
146 y = PyNumber_Subtract(x, one); /* -(2**(NBITS-1))-1 */
147 UNBIND(x);
148 if (y == NULL)
149 return F_ERROR(
150 "unexpected NULL from PyNumber_Subtract");
151
152 out = F_PY_TO_S(y);
153 if (out != (TYPENAME)-1 || !PyErr_Occurred())
154 return F_ERROR(
155 "PyLong_AsXXX(-2**(NBITS-1)-1) didn't "
156 "complain");
157 PyErr_Clear();
158 UNBIND(y);
159
160 Py_XDECREF(x);
161 Py_XDECREF(y);
162 Py_DECREF(one);
163 }
164
165 Py_INCREF(Py_None);
166 return Py_None;
167}