-
Notifications
You must be signed in to change notification settings - Fork 3
/
test.py
143 lines (105 loc) · 4.01 KB
/
test.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
from __future__ import print_function
import sys
import random
import string
import unittest
from perfect_hash import (
generate_hash, Graph, Format, StrSaltHash, IntSaltHash,
generate_code, run_code, builtin_template, TooManyInterationsError,
)
Hashes = StrSaltHash, IntSaltHash
def flush_dot():
sys.stdout.write('.')
sys.stdout.flush()
def random_keys(N):
keys = set()
while len(keys) < N:
keys.add(''.join(
random.choice(string.ascii_letters + string.digits)
for i in range(random.randint(1, 7))))
keys = list(keys)
random.shuffle(keys)
return keys
class TestsGraph(unittest.TestCase):
def test_basic(self):
G = Graph(3)
# is acyclic
self.assertTrue(G.assign_vertex_values())
# now we make an edge between vertex 0 and 1 with desired edge value 2
G.connect(0, 1, 2)
# the graph is still acyclic
self.assertTrue(G.assign_vertex_values())
# make another edge 1:2 with desired edge value 1
G.connect(1, 2, 1)
self.assertTrue(G.assign_vertex_values())
self.assertEqual(G.vertex_values, [0, 2, 2])
# What do these values mean?
# When you add the values for edge 0:1 you get 0 + 2 = 2, as desired.
# For edge 1:2 you add 2 + 2 = 4 = 1 (mod 3), as desired.
# adding edge 0:2 produces a loop, so the graph is no longer acyclic
G.connect(0, 2, 0)
self.assertFalse(G.assign_vertex_values())
class TestsFormat(unittest.TestCase):
def test_basic(self):
x = Format(delimiter=': ')
self.assertEqual(x(list(range(7))), '0: 1: 2: 3: 4: 5: 6')
x = Format(delimiter='; ')
self.assertEqual(x(list(range(5))), '0; 1; 2; 3; 4')
x = Format(delimiter=' ')
self.assertEqual(x(list(range(5)), quote=True),
'"0" "1" "2" "3" "4"')
self.assertEqual(x(42), '42')
self.assertEqual(x('Hello'), 'Hello')
class TestsGenerateHash(unittest.TestCase):
def test_args(self):
generate_hash(["A", "B"])
self.assertRaises(TypeError, generate_hash, {})
self.assertRaises(TypeError, generate_hash, ["A", 8])
def create_and_verify(self, keys, Hash):
f1, f2, G = generate_hash(keys, Hash)
f = lambda k: (G[f1(k)] + G[f2(k)]) % len(G)
for i, k in enumerate(keys):
self.assertEqual(i, f(k))
flush_dot()
def test_simple(self):
for Hash in Hashes:
self.create_and_verify(["Ilan", "Arvin"], Hash)
def test_letters(self):
for K in range(0, 27):
keys = [chr(65 + i) for i in range(K)]
random.shuffle(keys)
for Hash in Hashes:
self.create_and_verify(keys, Hash)
def test_random(self):
for Hash in Hashes:
for N in range(0, 50):
self.create_and_verify(random_keys(N), Hash)
def test_too_many_iterations(self):
def Hash(N):
# the returned hash function has no random salt
return lambda key: hash(key) % N
keys = ['kg', 'jG']
self.assertRaises(TooManyInterationsError,
generate_hash, keys, Hash)
class TestsGenerateCode(unittest.TestCase):
def test_args(self):
run_code(generate_code(["A", "B"]))
run_code(generate_code(["A", "B"],
IntSaltHash, builtin_template(IntSaltHash)))
def run_keys(self, keys, Hash):
code = generate_code(keys, Hash)
run_code(code)
flush_dot()
def test_simple(self):
for Hash in Hashes:
self.run_keys(["Ilan", "Arvin"], Hash)
def test_random(self):
for Hash in Hashes:
self.run_keys(random_keys(50), Hash)
if __name__ == '__main__':
import perfect_hash
print('Python location:', sys.executable)
print('Python version:', sys.version)
print('perfect_hash location:', perfect_hash.__file__)
print('perfect_hash version:', perfect_hash.__version__)
unittest.main()