Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit c6aea46

Browse filesBrowse files
encukouskirpichev
andauthored
[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 * sumprod: L2744, L2754, L2774, L2778, L2781, L2785, L2831, L2835, L2838 * 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>
1 parent 9aa5ff8 commit c6aea46
Copy full SHA for c6aea46

File tree

Expand file treeCollapse file tree

1 file changed

+96
-0
lines changed
Filter options
Expand file treeCollapse file tree

1 file changed

+96
-0
lines changed

‎Lib/test/test_math.py

Copy file name to clipboardExpand all lines: Lib/test/test_math.py
+96Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,10 @@ def __init__(self, value):
235235
def __index__(self):
236236
return self.value
237237

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

240244
def ftest(self, name, got, expected, ulp_tol=5, abs_tol=0.0):
@@ -324,6 +328,7 @@ def testAtan2(self):
324328
self.ftest('atan2(0, 1)', math.atan2(0, 1), 0)
325329
self.ftest('atan2(1, 1)', math.atan2(1, 1), math.pi/4)
326330
self.ftest('atan2(1, 0)', math.atan2(1, 0), math.pi/2)
331+
self.ftest('atan2(1, -1)', math.atan2(1, -1), 3*math.pi/4)
327332

328333
# math.atan2(0, x)
329334
self.ftest('atan2(0., -inf)', math.atan2(0., NINF), math.pi)
@@ -417,16 +422,22 @@ def __ceil__(self):
417422
return 42
418423
class TestNoCeil:
419424
pass
425+
class TestBadCeil:
426+
__ceil__ = BadDescr()
420427
self.assertEqual(math.ceil(TestCeil()), 42)
421428
self.assertEqual(math.ceil(FloatCeil()), 42)
422429
self.assertEqual(math.ceil(FloatLike(42.5)), 43)
423430
self.assertRaises(TypeError, math.ceil, TestNoCeil())
431+
self.assertRaises(ValueError, math.ceil, TestBadCeil())
424432

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

438+
self.assertEqual(math.ceil(FloatLike(+1.0)), +1.0)
439+
self.assertEqual(math.ceil(FloatLike(-1.0)), -1.0)
440+
430441
@requires_IEEE_754
431442
def testCopysign(self):
432443
self.assertEqual(math.copysign(1, 42), 1.0)
@@ -567,16 +578,22 @@ def __floor__(self):
567578
return 42
568579
class TestNoFloor:
569580
pass
581+
class TestBadFloor:
582+
__floor__ = BadDescr()
570583
self.assertEqual(math.floor(TestFloor()), 42)
571584
self.assertEqual(math.floor(FloatFloor()), 42)
572585
self.assertEqual(math.floor(FloatLike(41.9)), 41)
573586
self.assertRaises(TypeError, math.floor, TestNoFloor())
587+
self.assertRaises(ValueError, math.floor, TestBadFloor())
574588

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

594+
self.assertEqual(math.floor(FloatLike(+1.0)), +1.0)
595+
self.assertEqual(math.floor(FloatLike(-1.0)), -1.0)
596+
580597
def testFmod(self):
581598
self.assertRaises(TypeError, math.fmod)
582599
self.ftest('fmod(10, 1)', math.fmod(10, 1), 0.0)
@@ -598,6 +615,7 @@ def testFmod(self):
598615
self.assertEqual(math.fmod(-3.0, NINF), -3.0)
599616
self.assertEqual(math.fmod(0.0, 3.0), 0.0)
600617
self.assertEqual(math.fmod(0.0, NINF), 0.0)
618+
self.assertRaises(ValueError, math.fmod, INF, INF)
601619

602620
def testFrexp(self):
603621
self.assertRaises(TypeError, math.frexp)
@@ -667,6 +685,7 @@ def msum(iterable):
667685
([], 0.0),
668686
([0.0], 0.0),
669687
([1e100, 1.0, -1e100, 1e-100, 1e50, -1.0, -1e50], 1e-100),
688+
([1e100, 1.0, -1e100, 1e-100, 1e50, -1, -1e50], 1e-100),
670689
([2.0**53, -0.5, -2.0**-54], 2.0**53-1.0),
671690
([2.0**53, 1.0, 2.0**-100], 2.0**53+2.0),
672691
([2.0**53+10.0, 1.0, 2.0**-100], 2.0**53+12.0),
@@ -714,6 +733,22 @@ def msum(iterable):
714733
s = msum(vals)
715734
self.assertEqual(msum(vals), math.fsum(vals))
716735

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

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

9771032
# Verify that the one dimensional case is equivalent to abs()
9781033
for i in range(20):
@@ -1111,6 +1166,7 @@ def test_lcm(self):
11111166

11121167
def testLdexp(self):
11131168
self.assertRaises(TypeError, math.ldexp)
1169+
self.assertRaises(TypeError, math.ldexp, 2.0, 1.1)
11141170
self.ftest('ldexp(0,1)', math.ldexp(0,1), 0)
11151171
self.ftest('ldexp(1,1)', math.ldexp(1,1), 2)
11161172
self.ftest('ldexp(1,-1)', math.ldexp(1,-1), 0.5)
@@ -1143,6 +1199,7 @@ def testLdexp(self):
11431199

11441200
def testLog(self):
11451201
self.assertRaises(TypeError, math.log)
1202+
self.assertRaises(TypeError, math.log, 1, 2, 3)
11461203
self.ftest('log(1/e)', math.log(1/math.e), -1)
11471204
self.ftest('log(1)', math.log(1), 0)
11481205
self.ftest('log(e)', math.log(math.e), 1)
@@ -1153,6 +1210,7 @@ def testLog(self):
11531210
2302.5850929940457)
11541211
self.assertRaises(ValueError, math.log, -1.5)
11551212
self.assertRaises(ValueError, math.log, -10**1000)
1213+
self.assertRaises(ValueError, math.log, 10, -10)
11561214
self.assertRaises(ValueError, math.log, NINF)
11571215
self.assertEqual(math.log(INF), INF)
11581216
self.assertTrue(math.isnan(math.log(NAN)))
@@ -1212,6 +1270,8 @@ def testSumProd(self):
12121270
self.assertEqual(sumprod(iter([10, 20, 30]), (1, 2, 3)), 140)
12131271
self.assertEqual(sumprod([1.5, 2.5], [3.5, 4.5]), 16.5)
12141272
self.assertEqual(sumprod([], []), 0)
1273+
self.assertEqual(sumprod([-1], [1.]), -1)
1274+
self.assertEqual(sumprod([1.], [-1]), -1)
12151275

12161276
# Type preservation and coercion
12171277
for v in [
@@ -1237,11 +1297,20 @@ def testSumProd(self):
12371297
self.assertRaises(TypeError, sumprod, [], [], []) # Three args
12381298
self.assertRaises(TypeError, sumprod, None, [10]) # Non-iterable
12391299
self.assertRaises(TypeError, sumprod, [10], None) # Non-iterable
1300+
self.assertRaises(TypeError, sumprod, ['x'], [1.0])
12401301

12411302
# Uneven lengths
12421303
self.assertRaises(ValueError, sumprod, [10, 20], [30])
12431304
self.assertRaises(ValueError, sumprod, [10], [20, 30])
12441305

1306+
# Overflows
1307+
self.assertEqual(sumprod([10**20], [1]), 10**20)
1308+
self.assertEqual(sumprod([1], [10**20]), 10**20)
1309+
self.assertEqual(sumprod([10**10], [10**10]), 10**20)
1310+
self.assertEqual(sumprod([10**7]*10**5, [10**7]*10**5), 10**19)
1311+
self.assertRaises(OverflowError, sumprod, [10**1000], [1.0])
1312+
self.assertRaises(OverflowError, sumprod, [1.0], [10**1000])
1313+
12451314
# Error in iterator
12461315
def raise_after(n):
12471316
for i in range(n):
@@ -1252,6 +1321,11 @@ def raise_after(n):
12521321
with self.assertRaises(RuntimeError):
12531322
sumprod(raise_after(5), range(10))
12541323

1324+
from test.test_iter import BasicIterClass
1325+
1326+
self.assertEqual(sumprod(BasicIterClass(1), [1]), 0)
1327+
self.assertEqual(sumprod([1], BasicIterClass(1)), 0)
1328+
12551329
# Error in multiplication
12561330
class BadMultiply:
12571331
def __mul__(self, other):
@@ -1491,6 +1565,7 @@ def testPow(self):
14911565
self.assertTrue(math.isnan(math.pow(2, NAN)))
14921566
self.assertTrue(math.isnan(math.pow(0, NAN)))
14931567
self.assertEqual(math.pow(1, NAN), 1)
1568+
self.assertRaises(OverflowError, math.pow, 1e+100, 1e+100)
14941569

14951570
# pow(0., x)
14961571
self.assertEqual(math.pow(0., INF), 0.)
@@ -1847,6 +1922,8 @@ def __trunc__(self):
18471922
return 23
18481923
class TestNoTrunc:
18491924
pass
1925+
class TestBadTrunc:
1926+
__trunc__ = BadDescr()
18501927

18511928
self.assertEqual(math.trunc(TestTrunc()), 23)
18521929
self.assertEqual(math.trunc(FloatTrunc()), 23)
@@ -1855,6 +1932,7 @@ class TestNoTrunc:
18551932
self.assertRaises(TypeError, math.trunc, 1, 2)
18561933
self.assertRaises(TypeError, math.trunc, FloatLike(23.5))
18571934
self.assertRaises(TypeError, math.trunc, TestNoTrunc())
1935+
self.assertRaises(ValueError, math.trunc, TestBadTrunc())
18581936

18591937
def testIsfinite(self):
18601938
self.assertTrue(math.isfinite(0.0))
@@ -2055,6 +2133,8 @@ def test_mtestfile(self):
20552133
'\n '.join(failures))
20562134

20572135
def test_prod(self):
2136+
from fractions import Fraction as F
2137+
20582138
prod = math.prod
20592139
self.assertEqual(prod([]), 1)
20602140
self.assertEqual(prod([], start=5), 5)
@@ -2066,6 +2146,14 @@ def test_prod(self):
20662146
self.assertEqual(prod([1.0, 2.0, 3.0, 4.0, 5.0]), 120.0)
20672147
self.assertEqual(prod([1, 2, 3, 4.0, 5.0]), 120.0)
20682148
self.assertEqual(prod([1.0, 2.0, 3.0, 4, 5]), 120.0)
2149+
self.assertEqual(prod([1., F(3, 2)]), 1.5)
2150+
2151+
# Error in multiplication
2152+
class BadMultiply:
2153+
def __rmul__(self, other):
2154+
raise RuntimeError
2155+
with self.assertRaises(RuntimeError):
2156+
prod([10., BadMultiply()])
20692157

20702158
# Test overflow in fast-path for integers
20712159
self.assertEqual(prod([1, 1, 2**32, 1, 1]), 2**32)
@@ -2379,6 +2467,14 @@ def __float__(self):
23792467
# argument to a float.
23802468
self.assertFalse(getattr(y, "converted", False))
23812469

2470+
def test_input_exceptions(self):
2471+
self.assertRaises(TypeError, math.exp, "spam")
2472+
self.assertRaises(TypeError, math.erf, "spam")
2473+
self.assertRaises(TypeError, math.atan2, "spam", 1.0)
2474+
self.assertRaises(TypeError, math.atan2, 1.0, "spam")
2475+
self.assertRaises(TypeError, math.atan2, 1.0)
2476+
self.assertRaises(TypeError, math.atan2, 1.0, 2.0, 3.0)
2477+
23822478
# Custom assertions.
23832479

23842480
def assertIsNaN(self, value):

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.