Skip to content

Commit ba324cb

Browse files
Add test
1 parent d65f958 commit ba324cb

File tree

2 files changed

+27
-6
lines changed

2 files changed

+27
-6
lines changed

Lib/test/test_tools/test_msgfmt.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
from test.support.os_helper import temp_cwd
1111
from test.support.script_helper import assert_python_failure, assert_python_ok
12-
from test.test_tools import skip_if_missing, toolsdir
12+
from test.test_tools import imports_under_tool, skip_if_missing, toolsdir
1313

1414

1515
skip_if_missing('i18n')
@@ -18,6 +18,9 @@
1818
script_dir = Path(toolsdir) / 'i18n'
1919
msgfmt = script_dir / 'msgfmt.py'
2020

21+
with imports_under_tool("i18n"):
22+
from msgfmt import _hashpjw
23+
2124

2225
def compile_messages(po_file, mo_file):
2326
assert_python_ok(msgfmt, '-o', mo_file, po_file)
@@ -42,7 +45,25 @@ def test_compilation(self):
4245
self.assertDictEqual(actual._catalog, expected._catalog)
4346

4447
def test_hash_table(self):
45-
pass
48+
# Check _hashpjw generates correct hash values
49+
self.assertEqual(_hashpjw(b"stan"), 502398)
50+
self.assertEqual(_hashpjw(b"foo"), 27999)
51+
52+
# Check hash table is generated correctly for general.po
53+
with temp_cwd():
54+
tmp_mo_file = "messages.mo"
55+
compile_messages(data_dir / "general.po", tmp_mo_file)
56+
with open(tmp_mo_file, "rb") as f:
57+
mo_data = f.read()
58+
59+
header = struct.unpack("=7I", mo_data[:28])
60+
hash_table_size, hash_table_offset = header[5:7]
61+
62+
hash_tab = struct.unpack(f"={hash_table_size}I",
63+
mo_data[hash_table_offset : hash_table_offset + (hash_table_size * 4)])
64+
65+
self.assertEqual(hash_tab, (1, 3, 0, 8, 9, 7, 2, 0, 4, 5, 0, 6, 0))
66+
4667

4768
def test_binary_header(self):
4869
with temp_cwd():

Tools/i18n/msgfmt.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ def generate():
6262
global MESSAGES
6363

6464
def hash_insert_entry(string, i):
65-
hash_val = hashpjw(string)
65+
hash_val = _hashpjw(string)
6666
hash_cursor = hash_val % hash_tab_size
6767
inc = 1 + (hash_val % (hash_tab_size - 2))
6868
while hash_table[hash_cursor]:
@@ -90,7 +90,7 @@ def hash_insert_entry(string, i):
9090
# Because unsuccessful searches are unlikely this is a good value.
9191
# Formulas: [Knuth, The Art of Computer Programming, Volume 3,
9292
# 766 Sorting and Searching, 1973, Addison Wesley]
93-
hash_tab_size = next_prime((len(MESSAGES) * 4) // 3)
93+
hash_tab_size = _next_prime((len(MESSAGES) * 4) // 3)
9494
if hash_tab_size <= 2:
9595
hash_tab_size = 3
9696
hash_table = array.array("I", [0] * hash_tab_size)
@@ -294,7 +294,7 @@ def main():
294294

295295
# Peter J. Weinberger hash function
296296
# See: https://www.drdobbs.com/database/hashing-rehashed/184409859
297-
def hashpjw(strs):
297+
def _hashpjw(strs):
298298
hval = 0
299299
for s in strs:
300300
if not s:
@@ -308,7 +308,7 @@ def hashpjw(strs):
308308
return hval
309309

310310

311-
def next_prime(start):
311+
def _next_prime(start):
312312
def is_prime(num):
313313
divn = 3
314314
sq = divn * divn

0 commit comments

Comments
 (0)