mirror of
https://github.com/python/cpython.git
synced 2025-08-04 08:59:19 +00:00
gh-102837: improve test coverage for math module (#102523)
- input checks for math_1(L989), math_1a(L1023), math_2(L1064,L1071), hypot(L2682), log(L2307), ldexp(L2168), ceil(L1165), floor(L1236,L1239) and dist(L2587,L2588,L2628).
- drop inaccessible "if" branch (L3518) in perm_comb_small()
- improve fsum coverage for exceptional cases (L1433,L1438,L1451,L1497), ditto fmod(L2378)
- rewrite modf to fix inaccessible case(L2229), ditto for pow(L2988)
(all line numbers are wrt the main branch at 5e6661bce9
)
This commit is contained in:
parent
f373c6b948
commit
9c995abd78
2 changed files with 48 additions and 10 deletions
|
@ -235,6 +235,10 @@ class MyIndexable(object):
|
|||
def __index__(self):
|
||||
return self.value
|
||||
|
||||
class BadDescr:
|
||||
def __get__(self, obj, objtype=None):
|
||||
raise ValueError
|
||||
|
||||
class MathTests(unittest.TestCase):
|
||||
|
||||
def ftest(self, name, got, expected, ulp_tol=5, abs_tol=0.0):
|
||||
|
@ -324,6 +328,7 @@ class MathTests(unittest.TestCase):
|
|||
self.ftest('atan2(0, 1)', math.atan2(0, 1), 0)
|
||||
self.ftest('atan2(1, 1)', math.atan2(1, 1), math.pi/4)
|
||||
self.ftest('atan2(1, 0)', math.atan2(1, 0), math.pi/2)
|
||||
self.ftest('atan2(1, -1)', math.atan2(1, -1), 3*math.pi/4)
|
||||
|
||||
# math.atan2(0, x)
|
||||
self.ftest('atan2(0., -inf)', math.atan2(0., NINF), math.pi)
|
||||
|
@ -417,16 +422,22 @@ class MathTests(unittest.TestCase):
|
|||
return 42
|
||||
class TestNoCeil:
|
||||
pass
|
||||
class TestBadCeil:
|
||||
__ceil__ = BadDescr()
|
||||
self.assertEqual(math.ceil(TestCeil()), 42)
|
||||
self.assertEqual(math.ceil(FloatCeil()), 42)
|
||||
self.assertEqual(math.ceil(FloatLike(42.5)), 43)
|
||||
self.assertRaises(TypeError, math.ceil, TestNoCeil())
|
||||
self.assertRaises(ValueError, math.ceil, TestBadCeil())
|
||||
|
||||
t = TestNoCeil()
|
||||
t.__ceil__ = lambda *args: args
|
||||
self.assertRaises(TypeError, math.ceil, t)
|
||||
self.assertRaises(TypeError, math.ceil, t, 0)
|
||||
|
||||
self.assertEqual(math.ceil(FloatLike(+1.0)), +1.0)
|
||||
self.assertEqual(math.ceil(FloatLike(-1.0)), -1.0)
|
||||
|
||||
@requires_IEEE_754
|
||||
def testCopysign(self):
|
||||
self.assertEqual(math.copysign(1, 42), 1.0)
|
||||
|
@ -567,16 +578,22 @@ class MathTests(unittest.TestCase):
|
|||
return 42
|
||||
class TestNoFloor:
|
||||
pass
|
||||
class TestBadFloor:
|
||||
__floor__ = BadDescr()
|
||||
self.assertEqual(math.floor(TestFloor()), 42)
|
||||
self.assertEqual(math.floor(FloatFloor()), 42)
|
||||
self.assertEqual(math.floor(FloatLike(41.9)), 41)
|
||||
self.assertRaises(TypeError, math.floor, TestNoFloor())
|
||||
self.assertRaises(ValueError, math.floor, TestBadFloor())
|
||||
|
||||
t = TestNoFloor()
|
||||
t.__floor__ = lambda *args: args
|
||||
self.assertRaises(TypeError, math.floor, t)
|
||||
self.assertRaises(TypeError, math.floor, t, 0)
|
||||
|
||||
self.assertEqual(math.floor(FloatLike(+1.0)), +1.0)
|
||||
self.assertEqual(math.floor(FloatLike(-1.0)), -1.0)
|
||||
|
||||
def testFmod(self):
|
||||
self.assertRaises(TypeError, math.fmod)
|
||||
self.ftest('fmod(10, 1)', math.fmod(10, 1), 0.0)
|
||||
|
@ -598,6 +615,7 @@ class MathTests(unittest.TestCase):
|
|||
self.assertEqual(math.fmod(-3.0, NINF), -3.0)
|
||||
self.assertEqual(math.fmod(0.0, 3.0), 0.0)
|
||||
self.assertEqual(math.fmod(0.0, NINF), 0.0)
|
||||
self.assertRaises(ValueError, math.fmod, INF, INF)
|
||||
|
||||
def testFrexp(self):
|
||||
self.assertRaises(TypeError, math.frexp)
|
||||
|
@ -714,6 +732,11 @@ class MathTests(unittest.TestCase):
|
|||
s = msum(vals)
|
||||
self.assertEqual(msum(vals), math.fsum(vals))
|
||||
|
||||
self.assertEqual(math.fsum([1.0, math.inf]), math.inf)
|
||||
self.assertRaises(OverflowError, math.fsum, [1e+308, 1e+308])
|
||||
self.assertRaises(ValueError, math.fsum, [math.inf, -math.inf])
|
||||
self.assertRaises(TypeError, math.fsum, ['spam'])
|
||||
|
||||
def testGcd(self):
|
||||
gcd = math.gcd
|
||||
self.assertEqual(gcd(0, 0), 0)
|
||||
|
@ -831,6 +854,8 @@ class MathTests(unittest.TestCase):
|
|||
scale = FLOAT_MIN / 2.0 ** exp
|
||||
self.assertEqual(math.hypot(4*scale, 3*scale), 5*scale)
|
||||
|
||||
self.assertRaises(TypeError, math.hypot, *([1.0]*18), 'spam')
|
||||
|
||||
@requires_IEEE_754
|
||||
@unittest.skipIf(HAVE_DOUBLE_ROUNDING,
|
||||
"hypot() loses accuracy on machines with double rounding")
|
||||
|
@ -966,6 +991,8 @@ class MathTests(unittest.TestCase):
|
|||
dist((1, 2, 3, 4), (5, 6, 7))
|
||||
with self.assertRaises(ValueError): # Check dimension agree
|
||||
dist((1, 2, 3), (4, 5, 6, 7))
|
||||
with self.assertRaises(TypeError):
|
||||
dist((1,)*17 + ("spam",), (1,)*18)
|
||||
with self.assertRaises(TypeError): # Rejects invalid types
|
||||
dist("abc", "xyz")
|
||||
int_too_big_for_float = 10 ** (sys.float_info.max_10_exp + 5)
|
||||
|
@ -973,6 +1000,10 @@ class MathTests(unittest.TestCase):
|
|||
dist((1, int_too_big_for_float), (2, 3))
|
||||
with self.assertRaises((ValueError, OverflowError)):
|
||||
dist((2, 3), (1, int_too_big_for_float))
|
||||
with self.assertRaises(TypeError):
|
||||
dist((1,), 2)
|
||||
with self.assertRaises(TypeError):
|
||||
dist([1], 2)
|
||||
|
||||
# Verify that the one dimensional case is equivalent to abs()
|
||||
for i in range(20):
|
||||
|
@ -1111,6 +1142,7 @@ class MathTests(unittest.TestCase):
|
|||
|
||||
def testLdexp(self):
|
||||
self.assertRaises(TypeError, math.ldexp)
|
||||
self.assertRaises(TypeError, math.ldexp, 2.0, 1.1)
|
||||
self.ftest('ldexp(0,1)', math.ldexp(0,1), 0)
|
||||
self.ftest('ldexp(1,1)', math.ldexp(1,1), 2)
|
||||
self.ftest('ldexp(1,-1)', math.ldexp(1,-1), 0.5)
|
||||
|
@ -1153,6 +1185,7 @@ class MathTests(unittest.TestCase):
|
|||
2302.5850929940457)
|
||||
self.assertRaises(ValueError, math.log, -1.5)
|
||||
self.assertRaises(ValueError, math.log, -10**1000)
|
||||
self.assertRaises(ValueError, math.log, 10, -10)
|
||||
self.assertRaises(ValueError, math.log, NINF)
|
||||
self.assertEqual(math.log(INF), INF)
|
||||
self.assertTrue(math.isnan(math.log(NAN)))
|
||||
|
@ -2378,6 +2411,14 @@ class MathTests(unittest.TestCase):
|
|||
# argument to a float.
|
||||
self.assertFalse(getattr(y, "converted", False))
|
||||
|
||||
def test_input_exceptions(self):
|
||||
self.assertRaises(TypeError, math.exp, "spam")
|
||||
self.assertRaises(TypeError, math.erf, "spam")
|
||||
self.assertRaises(TypeError, math.atan2, "spam", 1.0)
|
||||
self.assertRaises(TypeError, math.atan2, 1.0, "spam")
|
||||
self.assertRaises(TypeError, math.atan2, 1.0)
|
||||
self.assertRaises(TypeError, math.atan2, 1.0, 2.0, 3.0)
|
||||
|
||||
# Custom assertions.
|
||||
|
||||
def assertIsNaN(self, value):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue