[Jython-checkins] jython: Update test.math_cmath to count/log the discrepancies
jeff.allen
jython-checkins at python.org
Tue Jan 20 23:07:17 CET 2015
https://hg.python.org/jython/rev/e89bf3a7c8dd
changeset: 7552:e89bf3a7c8dd
user: Jeff Allen <ja.py at farowl.co.uk>
date: Tue Jan 20 19:17:32 2015 +0000
summary:
Update test.math_cmath to count/log the discrepancies
test_cmath is skip-free. The case test_cmath_matches_math tests more
functions, and test_specific_values no longer exits at the first
failure, but counts them. Error detail useful to cmath development is
reported in verbose mode.
files:
Lib/test/test_cmath.py | 144 ++++++++++--------
NEWS | 2 +
src/org/python/modules/cmath.java | 25 +--
3 files changed, 87 insertions(+), 84 deletions(-)
diff --git a/Lib/test/test_cmath.py b/Lib/test/test_cmath.py
--- a/Lib/test/test_cmath.py
+++ b/Lib/test/test_cmath.py
@@ -1,4 +1,4 @@
-from test.test_support import run_unittest, is_jython
+from test.test_support import run_unittest, verbose
from test.test_math import parse_testfile, test_file
import unittest
import cmath, math
@@ -52,7 +52,6 @@
'cos', 'cosh', 'exp', 'log', 'log10', 'sin', 'sinh',
'sqrt', 'tan', 'tanh']]
# test first and second arguments independently for 2-argument log
-
test_functions.append(lambda x : cmath.log(x, 1729. + 0j))
test_functions.append(lambda x : cmath.log(14.-27j, x))
@@ -244,24 +243,30 @@
unit_interval = test_values + [-x for x in test_values] + \
[0., 1., -1.]
+ # test_values for acosh, atanh
+ ge_one = [1.] + [1./x for x in test_values]
+ unit_open = test_values + [-x for x in test_values] + [0.]
+
# test_values for log, log10, sqrt
- positive = test_values + [1.] + [1./x for x in test_values]
+ positive = test_values + ge_one
nonnegative = [0.] + positive
# test_values for functions defined on the whole real line
real_line = [0.] + positive + [-x for x in positive]
test_functions = {
- # FIXME uncomment tests for Jython
- #'acos' : unit_interval,
- #'asin' : unit_interval,
- #'atan' : real_line,
- #'cos' : real_line,
- #'cosh' : real_line,
+ 'acos' : unit_interval,
+ 'asin' : unit_interval,
+ 'atan' : real_line,
+ 'acosh' : ge_one, # Jython added
+ 'asinh' : real_line, # Jython added
+ 'atanh' : unit_open, # Jython added
+ 'cos' : real_line,
+ 'cosh' : real_line,
'exp' : real_line,
'log' : positive,
'log10' : positive,
- #'sin' : real_line,
+ 'sin' : real_line,
'sinh' : real_line,
'sqrt' : nonnegative,
'tan' : real_line,
@@ -273,7 +278,7 @@
for v in values:
z = complex_fn(v)
self.rAssertAlmostEqual(float_fn(v), z.real)
- self.rAssertAlmostEqual(0., z.imag)
+ self.assertEqual(0., z.imag)
# test two-argument version of log with various bases
for base in [0.5, 2., 10.]:
@@ -282,10 +287,9 @@
self.rAssertAlmostEqual(math.log(v, base), z.real)
self.assertEqual(0., z.imag)
- @unittest.skipIf(is_jython, "FIXME: not working in Jython")
def test_specific_values(self):
if not float.__getformat__("double").startswith("IEEE"):
- return
+ self.skipTest('needs IEEE double')
def rect_complex(z):
"""Wrapped version of rect that accepts a complex number instead of
@@ -297,78 +301,88 @@
two floats."""
return complex(*polar(z))
+ raised_fmt = '\n' \
+ '{}: {}(complex({!r}, {!r}))\n' \
+ 'Raised: {!r}\n' \
+ 'Expected: complex({!r}, {!r})'
+ not_raised_fmt = '\n' \
+ '{} not raised in test {}: {}(complex({!r}, {!r}))\n' \
+ 'Received: complex({!r}, {!r})'
+ value_fmt = '\n' \
+ '{}: {}(complex({!r}, {!r}))\n' \
+ 'Expected: complex({!r}, {!r})\n' \
+ 'Received: complex({!r}, {!r})\n' \
+ 'Received value insufficiently close to expected value.'
+ failures = 0
+
for id, fn, ar, ai, er, ei, flags in parse_testfile(test_file):
arg = complex(ar, ai)
- expected = complex(er, ei)
if fn == 'rect':
function = rect_complex
elif fn == 'polar':
function = polar_complex
else:
function = getattr(cmath, fn)
- if 'divide-by-zero' in flags or 'invalid' in flags:
- try:
+
+ try:
+ # Catch and count failing test cases locally
+ if 'divide-by-zero' in flags or 'invalid' in flags:
try:
actual = function(arg)
except ValueError:
- continue
+ pass
else:
- self.fail('ValueError not raised in test '
- '{}: {}(complex({!r}, {!r}))'.format(id, fn, ar, ai))
- except AssertionError, ex:
- print "Got", function, ex
- except BaseException, ex:
- print "Got", function, ex
+ failures += 1
+ self.fail(not_raised_fmt.format('ValueError',
+ id, fn, ar, ai, actual.real, actual.imag))
- try:
- if 'overflow' in flags:
+ elif 'overflow' in flags:
try:
actual = function(arg)
except OverflowError:
- continue
- except BaseException, ex:
- print "\nGot", function, ex
+ pass
else:
- self.fail('OverflowError not raised in test '
- '{}: {}(complex({!r}, {!r}))'.format(id, fn, ar, ai))
- except AssertionError, ex:
- print "\nGot", function, ex
+ failures += 1
+ self.fail(not_raised_fmt.format('OverflowError',
+ id, fn, ar, ai, actual.real, actual.imag))
- try:
- actual = function(arg)
- except BaseException, ex:
- print "\nGot", function, ex
+ else :
+ actual = function(arg)
- if 'ignore-real-sign' in flags:
- actual = complex(abs(actual.real), actual.imag)
- expected = complex(abs(expected.real), expected.imag)
- if 'ignore-imag-sign' in flags:
- actual = complex(actual.real, abs(actual.imag))
- expected = complex(expected.real, abs(expected.imag))
+ # Make sign of expected conform to actual, where ignored.
+ exr, exi = er, ei
+ if 'ignore-real-sign' in flags:
+ exr = math.copysign(er, actual.real)
+ if 'ignore-imag-sign' in flags:
+ exi = math.copysign(ei, actual.imag)
- # for the real part of the log function, we allow an
- # absolute error of up to 2e-15.
- if fn in ('log', 'log10'):
- real_abs_err = 2e-15
- else:
- real_abs_err = 5e-323
+ # for the real part of the log function, we allow an
+ # absolute error of up to 2e-15.
+ if fn in ('log', 'log10'):
+ real_abs_err = 2e-15
+ else:
+ real_abs_err = 5e-323
- error_message = (
- '{}: {}(complex({!r}, {!r}))\n'
- 'Expected: complex({!r}, {!r})\n'
- 'Received: complex({!r}, {!r})\n'
- 'Received value insufficiently close to expected value.'
- ).format(id, fn, ar, ai,
- expected.real, expected.imag,
- actual.real, actual.imag)
- try:
- self.rAssertAlmostEqual(expected.real, actual.real,
- abs_err=real_abs_err,
- msg=error_message)
- self.rAssertAlmostEqual(expected.imag, actual.imag,
- msg=error_message)
- except AssertionError, ex:
- print "\nGot", ex, error_message
+ error_message = value_fmt.format(id, fn, ar, ai, er, ei,
+ actual.real, actual.imag)
+ self.rAssertAlmostEqual(exr, actual.real,
+ abs_err=real_abs_err,
+ msg=error_message)
+ self.rAssertAlmostEqual(exi, actual.imag,
+ msg=error_message)
+
+ except AssertionError as ex:
+ failures += 1
+ if verbose :
+ print(ex)
+ except BaseException as ex:
+ failures += 1
+ if verbose :
+ print(raised_fmt.format(id, fn, ar, ai, ex, er, ei))
+
+ if failures :
+ self.fail('{} discrepancies'.format(failures))
+
def assertCISEqual(self, a, b):
eps = 1E-7
@@ -446,6 +460,8 @@
self.assertTrue(math.isnan(abs(complex(2.3, NAN))))
self.assertEqual(abs(complex(INF, NAN)), INF)
self.assertTrue(math.isnan(abs(complex(NAN, NAN))))
+
+ # result overflows
if float.__getformat__("double").startswith("IEEE"):
self.assertRaises(OverflowError, abs, complex(1.4e308, 1.4e308))
diff --git a/NEWS b/NEWS
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,8 @@
Jython 2.7b4
Bugs Fixed
- [ 2037 ] Byte-string containing elements greater than 255
+ - [ 2244 ] Weak testing of real math module
+ - [ 2237 ] Test failures with float and complex
Jython 2.7b3
Bugs Fixed
diff --git a/src/org/python/modules/cmath.java b/src/org/python/modules/cmath.java
--- a/src/org/python/modules/cmath.java
+++ b/src/org/python/modules/cmath.java
@@ -1145,6 +1145,11 @@
}
}
+ /**
+ * Raise <code>ValueError</code> if <code>result</code> is a <code>NaN</code>, but neither
+ * <code>a</code> nor <code>b</code> is <code>NaN</code>. Same as
+ * {@link #exceptNaN(PyComplex, PyComplex)}.
+ */
private static PyComplex exceptNaN(PyComplex result, double a, double b) throws PyException {
if ((Double.isNaN(result.real) || Double.isNaN(result.imag))
&& !(Double.isNaN(a) || Double.isNaN(b))) {
@@ -1154,24 +1159,4 @@
}
}
- /**
- * Turn an infinite result into a thrown <code>OverflowError</code>, a math range error, if the
- * original argument was not itself infinite. A <code>PyComplex</code> is infinite if either
- * component is infinite.
- *
- * @param result to return (if we return)
- * @param arg to include in check
- * @return result if <code>arg</code> was infinite or <code>result</code> was not infinite
- * @throws PyException (ValueError) if <code>result</code> was infinite and <code>arg</code> was
- * not infinite
- */
- private static PyComplex exceptInf(PyComplex result, PyComplex arg) {
- if ((Double.isInfinite(result.real) || Double.isInfinite(result.imag))
- && !(Double.isInfinite(arg.real) || Double.isInfinite(arg.imag))) {
- throw math.mathRangeError();
- } else {
- return result;
- }
- }
-
}
--
Repository URL: https://hg.python.org/jython
More information about the Jython-checkins
mailing list