modul-x / tests /test_i18n.py
FortyDN Dev
v3.0.0: fully autonomous engine — remove MillionVerifier, add DoH DNS worker, AI risk scorer (HF PRO, circuit breaker), i18n, normalized verdicts, remote SMTP worker
de745bf
Raw History Blame Contribute Delete
2.07 kB
"""Internationalization primitives (spec §7.1 Punycode / §7.2 SMTPUTF8)."""
import unittest
from app.validator.i18n import (
EAI_REASON,
domain_is_unicode,
eai_gate,
local_part_is_ascii,
to_punycode,
)
class PunycodeTests(unittest.TestCase):
def test_ascii_domain_untouched(self):
self.assertEqual(to_punycode("example.com"), "example.com")
def test_unicode_domain_encoded(self):
out = to_punycode("bücher.example")
self.assertTrue(out.startswith("xn--"))
self.assertEqual(out.encode("ascii").decode(), out)
def test_already_punycode_roundtrip(self):
self.assertEqual(to_punycode("xn--bcher-kva.example"), "xn--bcher-kva.example")
def test_unicode_tld(self):
out = to_punycode("пример.рф")
self.assertTrue(all(ord(c) < 128 for c in out))
self.assertIn("xn--", out)
def test_garbage_domain_returns_as_is(self):
# Must never raise — DNS will fail naturally and the verdict degrades.
self.assertEqual(to_punycode("\x00bad"), "\x00bad")
def test_empty_and_dot_stripping_safe(self):
self.assertEqual(to_punycode(""), "")
self.assertEqual(to_punycode("example.com"), "example.com")
class UnicodeDetectionTests(unittest.TestCase):
def test_domain_is_unicode(self):
self.assertTrue(domain_is_unicode("münchen.de"))
self.assertFalse(domain_is_unicode("xn--mnchen-3ya.de"))
self.assertFalse(domain_is_unicode("example.com"))
class EAITests(unittest.TestCase):
def test_ascii_local_passes_gate(self):
self.assertIsNone(eai_gate("john.smith"))
self.assertIsNone(eai_gate("o+brien+tag"))
def test_unicode_local_blocked_deterministically(self):
self.assertEqual(eai_gate("用户"), EAI_REASON)
self.assertEqual(eai_gate("café"), EAI_REASON)
def test_ascii_flag_consistency(self):
self.assertTrue(local_part_is_ascii("simple"))
self.assertFalse(local_part_is_ascii("日本語"))
if __name__ == "__main__":
unittest.main()