8000 [3.11] gh-102837: more tests for the math module (GH-111930)(GH-10252… · python/cpython@132a749 · GitHub
[go: up one dir, main page]

Skip to content

Commit 132a749

Browse files
encukouskirpichev
andauthored
[3.11] gh-102837: more tests for the math module (GH-111930)(GH-102523) (GH-112030) (GH-112041)
[3.12] gh-102837: more tests for the math module (GH-111930)(GH-102523) (GH-112030) * gh-102837: improve test coverage for math module (GH-102523) (Only the test changes from GH-102523 are cherry-picked) - 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). - improve fsum coverage for exceptional cases (L1433,L1438,L1451,L1497), ditto fmod(L2378) (all line numbers are wrt the main branch at 5e6661b) * gh-102837: more tests for the math module (GH-111930) Add tests to improve coverage: * fsum: L1369, L1379, L1383, L1412 * trunc: L2081 * log: L2267 * dist: L2577, L2579 * hypot: L2632 * (not cherry-picked for 3.11: sumprod) * pow: L2982 * prod: L3294, L3308, L3318-3330 // line numbers wrt to 9dc4fb8 (cherry picked from commit c61de45) --------- Co-authored-by: Sergey B Kirpichev <skirpichev@gmail.com> (cherry picked from commit c6aea46)
1 parent cdfef0c commit 132a749

File tree

1 file changed

+80
-0
lines changed

1 file changed

+80
-0
lines changed

Lib/test/test_math.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,10 @@ def __init__(self, value):
234234
def __index__(self):
235235
return self.value
236236

237+
class BadDescr:
238+
def __get__(self, obj, objtype=None):
239+
raise ValueError
240+
237241
class MathTests(unittest.TestCase):
238242

239243
def ftest(self, name, got, expected, ulp_tol=5, abs_tol=0.0):
@@ -323,6 +327,7 @@ def testAtan2(self):
323327
self.ftest('atan2(0, 1)', math.atan2(0, 1), 0)
324328
self.ftest('atan2(1, 1)', math.atan2(1, 1), math.pi/4)
325329
self.ftest('atan2(1, 0)', math.atan2(1, 0), math.pi/2)
330+
self.ftest('atan2(1, -1)', math.atan2(1, -1), 3*math.pi/4)
326331

327332
# math.atan2(0, x)
328333
self.ftest('atan2(0., -inf)', math.atan2(0., NINF), math.pi)
@@ -416,16 +421,22 @@ def __ceil__(self):
416421
return 42
417422
class TestNoCeil:
418423
pass
424+
class TestBadCeil:
425+
__ceil__ = BadDescr()
419426
self.assertEqual(math.ceil(TestCeil()), 42)
420427
self.assertEqual(math.ceil(FloatCeil()), 42)
421428
self.assertEqual(math.ceil(FloatLike(42.5)), 43)
422429
self.assertRaises(TypeError, math.ceil, TestNoCeil())
430+
self.assertRaises(ValueError, math.ceil, TestBadCeil())
423431

424432
t = TestNoCeil()
425433
t.__ceil__ = lambda *args: args
426434
self.assertRaises(TypeError, math.ceil, t)
427435
self.assertRaises(TypeError, math.ceil, t, 0)
428436

437+
self.assertEqual(math.ceil(FloatLike(+1.0)), +1.0)
438+
self.assertEqual(math.ceil(FloatLike(-1.0)), -1.0)
439+
429440
@requires_IEEE_754
430441
def testCopysign(self):
431442
self.assertEqual(math.copysign(1, 42), 1.0)
@@ -566,16 +577,22 @@ def __floor__(self):
566577
return 42
567578
class TestNoFloor:
568579
pass
580+
class TestBadFloor:
581+
__floor__ = BadDescr()
569582
self.assertEqual(math.floor(TestFloor()), 42)
570583
self.assertEqual(math.floor(FloatFloor()), 42)
571584
self.assertEqual(math.floor(FloatLike(41.9)), 41)
572585
self.assertRaises(TypeError, math.floor, TestNoFloor())
586+
self.assertRaises(ValueError, math.floor, TestBadFloor())
573587

574588
t = TestNoFloor()
575589
t.__floor__ = lambda *args: args
576590
self.assertRaises(TypeError, math.floor, t)
577591
self.assertRaises(TypeError, math.floor, t, 0)
578592

593+
self.assertEqual(math.floor(FloatLike(+1.0)), +1.0)
594+
self.assertEqual(math.floor(FloatLike(-1.0)), -1.0)
595+
579596
def testFmod(self):
580597
self.assertRaises(TypeError, math.fmod)
581598
self.ftest('fmod(10, 1)', math.fmod(10, 1), 0.0)
@@ -597,6 +614,7 @@ def testFmod(self):
597614
self.assertEqual(math.fmod(-3.0, NINF), -3.0)
598615
self.assertEqual(math.fmod(0.0, 3.0), 0.0)
599616
self.assertEqual(math.fmod(0.0, NINF), 0.0)
617+
self.assertRaises(ValueError, math.fmod, INF, INF)
600618

601619
def testFrexp(self):
602620
self.assertRaises(TypeError, math.frexp)
@@ -666,6 +684,7 @@ def msum(iterable):
666684
([], 0.0),
667685
([0.0], 0.0),
668686
([1e100, 1.0, -1e100, 1e-100, 1e50, -1.0, -1e50], 1e-100),
687+
([1e100, 1.0, -1e100, 1e-100, 1e50, -1, -1e50], 1e-100),
669688
([2.0**53, -0.5, -2.0**-54], 2.0**53-1.0),
670689
([2.0**53, 1.0, 2.0**-100], 2.0**53+2.0),
671690
([2.0**53+10.0, 1.0, 2.0**-100], 2.0**53+12.0),
@@ -713,6 +732,22 @@ def msum(iterable):
713732
s = msum(vals)
714733
self.assertEqual(msum(vals), math.fsum(vals))
715734

735+
self.assertEqual(math.fsum([1.0, math.inf]), math.inf)
736+
self.assertTrue(math.isnan(math.fsum([math.nan, 1.0])))
737+
self.assertEqual(math.fsum([1e100, FloatLike(1.0), -1e100, 1e-100,
738+
1e50, FloatLike(-1.0), -1e50]), 1e-100)
739+
self.assertRaises(OverflowError, math.fsum, [1e+308, 1e+308])
740+
self.assertRaises(ValueError, math.fsum, [math.inf, -math.inf])
741+
self.assertRaises(TypeError, math.fsum, ['spam'])
742+
self.assertRaises(TypeError, math.fsum, 1)
743+
self.assertRaises(OverflowError, math.fsum, [10**1000])
744+
745+
def bad_iter():
746+
yield 1.0
747+
raise ZeroDivisionError
748+
749+
self.assertRaises(ZeroDivisionError, math.fsum, bad_iter())
750+
716751
def testGcd(self):
717752
gcd = math.gcd
718753
self.assertEqual(gcd(0, 0), 0)
@@ -773,6 +808,8 @@ def testHypot(self):
773808
# Test allowable types (those with __float__)
774809
self.assertEqual(hypot(12.0, 5.0), 13.0)
775810
self.assertEqual(hypot(12, 5), 13)
811+
self.assertEqual(hypot(1, -1), math.sqrt(2))
812+
self.assertEqual(hypot(1, FloatLike(-1.)), math.sqrt(2))
776813
self.assertEqual(hypot(Decimal(12), Decimal(5)), 13)
777814
self.assertEqual(hypot(Fraction(12, 32), Fraction(5, 32)), Fraction(13, 32))
778815
self.assertEqual(hypot(bool(1), bool(0), bool(1), bool(1)), math.sqrt(3))
@@ -830,6 +867,8 @@ def testHypot(self):
830867
scale = FLOAT_MIN / 2.0 ** exp
831868
self.assertEqual(math.hypot(4*scale, 3*scale), 5*scale)
832869

870+
self.assertRaises(TypeError, math.hypot, *([1.0]*18), 'spam')
871+
833872
@requires_IEEE_754
834873
@unittest.skipIf(HAVE_DOUBLE_ROUNDING,
835874
"hypot() loses accuracy on machines with double rounding")
@@ -922,6 +961,10 @@ def testDist(self):
922961
# Test allowable types (those with __float__)
923962
self.assertEqual(dist((14.0, 1.0), (2.0, -4.0)), 13.0)
924963
self.assertEqual(dist((14, 1), (2, -4)), 13)
964+
self.assertEqual(dist((FloatLike(14.), 1), (2, -4)), 13)
965+
self.assertEqual(dist((11, 1), (FloatLike(-1.), -4)), 13)
966+
self.assertEqual(dist((14, FloatLike(-1.)), (2, -6)), 13)
967+
self.assertEqual(dist((14, -1), (2, -6)), 13)
925968
self.assertEqual(dist((D(14), D(1)), (D(2), D(-4))), D(13))
926969
self.assertEqual(dist((F(14, 32), F(1, 32)), (F(2, 32), F(-4, 32))),
927970
F(13, 32))
@@ -965,13 +1008,25 @@ class T(tuple):
9651008
dist((1, 2, 3, 4), (5, 6, 7))
9661009
with self.assertRaises(ValueError): # Check dimension agree
9671010
dist((1, 2, 3), (4, 5, 6, 7))
1011+
with self.assertRaises(TypeError):
1012+
dist((1,)*17 + ("spam",), (1,)*18)
9681013
with self.assertRaises(TypeError): # Rejects invalid types
9691014
dist("abc", "xyz")
9701015
int_too_big_for_float = 10 ** (sys.float_info.max_10_exp + 5)
9711016
with self.assertRaises((ValueError, OverflowError)):
9721017
dist((1, int_too_big_for_float), (2, 3))
9731018
with self.assertRaises((ValueError, OverflowError)):
9741019
dist((2, 3), (1, int_too_big_for_float))
1020+
with self.assertRaises(TypeError):
1021+
dist((1,), 2)
1022+
with self.assertRaises(TypeError):
1023+
dist([1], 2)
1024+
1025+
class BadFloat:
1026+
__float__ = BadDescr()
1027+
1028+
with self.assertRaises(ValueError):
1029+
dist([1], [BadFloat()])
9751030

9761031
# Verify that the one dimensional case is equivalent to abs()
9771032
for i in range(20):
@@ -1110,6 +1165,7 @@ def test_lcm(self):
11101165

11111166
def testLdexp(self):
11121167
self.assertRaises(TypeError, math.ldexp)
1168+
self.assertRaises(TypeError, math.ldexp, 2.0, 1.1)
11131169
self.ftest('ldexp(0,1)', math.ldexp(0,1), 0)
11141170
self.ftest('ldexp(1,1)', math.ldexp(1,1), 2)
11151171
self.ftest('ldexp(1,-1)', math.ldexp(1,-1), 0.5)
@@ -1142,6 +1198,7 @@ def testLdexp(self):
11421198

11431199
def testLog(self):
11441200
self.assertRaises(TypeError, math.log)
1201+
self.assertRaises(TypeError, math.log, 1, 2, 3)
11451202
self.ftest('log(1/e)', math.log(1/math.e), -1)
11461203
self.ftest('log(1)', math.log(1), 0)
11471204
self.ftest('log(e)', math.log(math.e), 1)
@@ -1152,6 +1209,7 1C6A @@ def testLog(self):
11521209
2302.5850929940457)
11531210
self.assertRaises(ValueError, math.log, -1.5)
11541211
self.assertRaises(ValueError, math.log, -10**1000)
1212+
self.assertRaises(ValueError, math.log, 10, -10)
11551213
self.assertRaises(ValueError, math.log, NINF)
11561214
self.assertEqual(math.log(INF), INF)
11571215
self.assertTrue(math.isnan(math.log(NAN)))
@@ -1235,6 +1293,7 @@ def testPow(self):
12351293
self.assertTrue(math.isnan(math.pow(2, NAN)))
12361294
self.assertTrue(math.isnan(math.pow(0, NAN)))
12371295
self.assertEqual(math.pow(1, NAN), 1)
1296+
self.assertRaises(OverflowError, math.pow, 1e+100, 1e+100)
12381297

12391298
# pow(0., x)
12401299
self.assertEqual(math.pow(0., INF), 0.)
@@ -1591,6 +1650,8 @@ def __trunc__(self):
15911650
return 23
15921651
class TestNoTrunc:
15931652
pass
1653+
class TestBadTrunc:
1654+
__trunc__ = BadDescr()
15941655

15951656
self.assertEqual(math.trunc(TestTrunc()), 23)
15961657
self.assertEqual(math.trunc(FloatTrunc()), 23)
@@ -1599,6 +1660,7 @@ class TestNoTrunc:
15991660
self.assertRaises(TypeError, math.trunc, 1, 2)
16001661
self.assertRaises(TypeError, math.trunc, FloatLike(23.5))
16011662
self.assertRaises(TypeError, math.trunc, TestNoTrunc())
1663+
self.assertRaises(ValueError, math.trunc, TestBadTrunc())
16021664

16031665
def testIsfinite(self):
16041666
self.assertTrue(math.isfinite(0.0))
@@ -1799,6 +1861,8 @@ def test_mtestfile(self):
17991861
'\n '.join(failures))
18001862

18011863
def test_prod(self):
1864+
from fractions import Fraction as F
1865+
18021866
prod = math.prod
18031867
self.assertEqual(prod([]), 1)
18041868
self.assertEqual(prod([], start=5), 5)
@@ -1810,6 +1874,14 @@ def test_prod(self):
18101874
self.assertEqual(prod([1.0, 2.0, 3.0, 4.0, 5.0]), 120.0)
18111875
self.assertEqual(prod([1, 2, 3, 4.0, 5.0]), 120.0)
18121876
self.assertEqual(prod([1.0, 2.0, 3.0, 4, 5]), 120.0)
1877+
self.assertEqual(prod([1., F(3, 2)]), 1.5)
1878+
1879+
# Error in multiplication
1880+
class BadMultiply:
1881+
def __rmul__(self, other):
1882+
raise RuntimeError
1883+
with self.assertRaises(RuntimeError):
1884+
prod([10., BadMultiply()])
18131885

18141886
# Test overflow in fast-path for integers
18151887
self.assertEqual(prod([1, 1, 2**32, 1, 1]), 2**32)
@@ -2109,6 +2181,14 @@ def __float__(self):
21092181
# argument to a float.
21102182
self.assertFalse(getattr(y, "converted", False))
21112183

2184+
def test_input_exceptions(self):
2185+
self.assertRaises(TypeError, math.exp, "spam")
2186+
self.assertRaises(TypeError, math.erf, "spam")
2187+
self.assertRaises(TypeError, math.atan2, "spam", 1.0)
2188+
self.assertRaises(TypeError, math.atan2, 1.0, "spam")
2189+
self.assertRaises(TypeError, math.atan2, 1.0)
2190+
self.assertRaises(TypeError, math.atan2, 1.0, 2.0, 3.0)
2191+
21122192
# Custom assertions.
21132193

21142194
def assertIsNaN(self, value):

0 commit comments

Comments
 (0)
0