Skip to content

Commit 7b394e8

Browse files
committed
test_numbertheory: test jacobi and factorization functions
make the jacobi test into a hypothesis test increase the range tested add test to verify factorization, since it's used in the jacobi test
1 parent b17549e commit 7b394e8

File tree

1 file changed

+44
-27
lines changed

1 file changed

+44
-27
lines changed

src/ecdsa/test_numbertheory.py

Lines changed: 44 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,12 @@
44
except ImportError:
55
import unittest
66
import hypothesis.strategies as st
7-
from hypothesis import given
7+
from hypothesis import given, settings, example
8+
try:
9+
from hypothesis import HealthCheck
10+
HC_PRESENT=True
11+
except ImportError:
12+
HC_PRESENT=False
813
from .numbertheory import (SquareRootError, factorization, gcd, lcm,
914
jacobi, inverse_mod,
1015
is_prime, next_prime, smallprimes,
@@ -79,32 +84,6 @@ def test_numbertheory():
7984
print_("Failed to report no root for sqrt( %d ) mod %d." % \
8085
(nonsquare, p))
8186

82-
# Test the jacobi function:
83-
for m in range(3, 400, 2):
84-
print_("Testing jacobi for modulus m = %d." % m)
85-
if is_prime(m):
86-
squares = []
87-
for root in range(1, m):
88-
if jacobi(root * root, m) != 1:
89-
error_tally = error_tally + 1
90-
print_("jacobi( %d * %d, %d) != 1" % (root, root, m))
91-
squares.append(root * root % m)
92-
for i in range(1, m):
93-
if i not in squares:
94-
if jacobi(i, m) != -1:
95-
error_tally = error_tally + 1
96-
print_("jacobi( %d, %d ) != -1" % (i, m))
97-
else: # m is not prime.
98-
f = factorization(m)
99-
for a in range(1, m):
100-
c = 1
101-
for i in f:
102-
c = c * jacobi(a, i[0]) ** i[1]
103-
if c != jacobi(a, m):
104-
error_tally = error_tally + 1
105-
print_("%d != jacobi( %d, %d )" % (c, a, m))
106-
107-
10887
class FailedTest(Exception):
10988
pass
11089

@@ -123,7 +102,45 @@ def st_two_nums_rel_prime(draw):
123102
return num, mod
124103

125104

105+
HYP_SETTINGS = {}
106+
if HC_PRESENT:
107+
HYP_SETTINGS['suppress_health_check']=[HealthCheck.filter_too_much,
108+
HealthCheck.too_slow]
109+
# the factorization() sometimes takes a long time to finish
110+
HYP_SETTINGS['deadline'] = 5000
111+
112+
126113
class TestNumbertheory(unittest.TestCase):
114+
@settings(**HYP_SETTINGS)
115+
@given(st.integers(min_value=1, max_value=10**12))
116+
@example(265399 * 1526929)
117+
@example(373297 ** 2 * 553991)
118+
def test_factorization(self, num):
119+
factors = factorization(num)
120+
mult = 1
121+
for i in factors:
122+
mult *= i[0] ** i[1]
123+
assert mult == num
124+
125+
@settings(**HYP_SETTINGS)
126+
@given(st.integers(min_value=3, max_value=1000).filter(lambda x: x % 2))
127+
def test_jacobi(self, mod):
128+
if is_prime(mod):
129+
squares = set()
130+
for root in range(1, mod):
131+
assert jacobi(root * root, mod) == 1
132+
squares.add(root * root % mod)
133+
for i in range(1, mod):
134+
if i not in squares:
135+
assert jacobi(i, mod) == -1
136+
else:
137+
factors = factorization(mod)
138+
for a in range(1, mod):
139+
c = 1
140+
for i in factors:
141+
c *= jacobi(a, i[0]) ** i[1]
142+
assert c == jacobi(a, mod)
143+
127144
@given(st_two_nums_rel_prime())
128145
def test_inverse_mod(self, nums):
129146
num, mod = nums

0 commit comments

Comments
 (0)