From cc16af76f52788c48ea267867e53d21ca2fd3868 Mon Sep 17 00:00:00 2001 From: nandgator <38415384+nandgator@users.noreply.github.com> Date: Sat, 10 Oct 2026 12:54:06 +0530 Subject: [PATCH 1/2] test: cover RFC length limits for domain() and hostname() --- tests/test_domain.py | 50 ++++++++++++++++++++++++++++++++++++++++++ tests/test_hostname.py | 35 +++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) diff --git a/tests/test_domain.py b/tests/test_domain.py index 1766212e..a3d990f1 100644 --- a/tests/test_domain.py +++ b/tests/test_domain.py @@ -110,3 +110,53 @@ def test_returns_failed_validation_invalid_top_level_domain( domain(value, consider_tld=consider_tld, rfc_1034=rfc_1034, rfc_2782=rfc_2782), ValidationError, ) + + +def _name_of_length(length: int): + """Build a dotted name of exactly `length` characters, ending with `.com`.""" + labels: list[str] = [] + remaining = length - len(".com") + while remaining > 0: + size = min(61, remaining) + if remaining - size == 1: # avoid leaving a lone "." behind + size -= 1 + labels.append("a" * size) + remaining -= size + 1 + name = ".".join(labels) + ".com" + assert len(name) == length + return name + + +@pytest.mark.parametrize( + "value", + [ + # total length: at most 253 characters (RFC 1035) + _name_of_length(253), + # label length: at most 63 characters (RFC 1035) + "a" * 63 + ".com", + # a label may start with a digit (RFC 1123) + "1host.example.com", + ], +) +def test_returns_true_on_domain_within_rfc_length_limits(value: str): + """Test returns true on domain within RFC length limits.""" + assert domain(value) + + +@pytest.mark.parametrize( + "value", + [ + _name_of_length(254), + _name_of_length(255), + # many short, dot-separated labels that exceed 253 characters; see #413 + ".".join(["kld8MXQh6YalMqKRbfs895gMjW5T4p2EwToPoCSThPHHbXgmXc"] * 4) + + ".kld8MXQh6YalMqKRbfs895gMjW5T4p2EwToPoCSThPHHbXgmXcab", + "a" * 64 + ".com", + # a label must not start or end with a hyphen + "-host.example.com", + "host-.example.com", + ], +) +def test_returns_failed_validation_on_domain_beyond_rfc_limits(value: str): + """Test returns failed validation on domain beyond RFC limits.""" + assert isinstance(domain(value), ValidationError) diff --git a/tests/test_hostname.py b/tests/test_hostname.py index b28e8044..90dada65 100644 --- a/tests/test_hostname.py +++ b/tests/test_hostname.py @@ -70,3 +70,38 @@ def test_returns_true_on_valid_hostname(value: str, rfc_1034: bool, rfc_2782: bo def test_returns_failed_validation_on_invalid_hostname(value: str, rfc_1034: bool, rfc_2782: bool): """Test returns failed validation on invalid hostname.""" assert isinstance(hostname(value, rfc_1034=rfc_1034, rfc_2782=rfc_2782), ValidationError) + + +@pytest.mark.parametrize( + "value", + [ + # total length: at most 253 characters (RFC 1035) + ".".join(["a" * 63, "a" * 63, "a" * 63, "a" * 61]), + # label length: at most 63 characters (RFC 1035) + "a" * 63 + ".com", + # a label may start with a digit (RFC 1123) + "1host.example.com", + ], +) +def test_returns_true_on_hostname_within_rfc_length_limits(value: str): + """Test returns true on hostname within RFC length limits.""" + assert hostname(value) + + +@pytest.mark.parametrize( + "value", + [ + # many short, dot-separated labels that exceed 253 characters; see #413 + ".".join(["kld8MXQh6YalMqKRbfs895gMjW5T4p2EwToPoCSThPHHbXgmXc"] * 4) + + ".kld8MXQh6YalMqKRbfs895gMjW5T4p2EwToPoCSThPHHbXgmXcab", + ".".join(["a" * 63, "a" * 63, "a" * 63, "a" * 62]), + "a" * 64 + ".com", + # a label must not start or end with a hyphen, nor contain an underscore + "-host.example.com", + "host-.example.com", + "ho_st.example.com", + ], +) +def test_returns_failed_validation_on_hostname_beyond_rfc_limits(value: str): + """Test returns failed validation on hostname beyond RFC limits.""" + assert isinstance(hostname(value), ValidationError) From 4478c68bbeffdf065bd34dfa5d6b43631e8ffa7b Mon Sep 17 00:00:00 2001 From: nandgator <38415384+nandgator@users.noreply.github.com> Date: Sat, 10 Oct 2026 12:56:50 +0530 Subject: [PATCH 2/2] test: cover IDN octet length and the #407 example --- tests/test_domain.py | 7 +++++++ tests/test_hostname.py | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/tests/test_domain.py b/tests/test_domain.py index a3d990f1..d606ad79 100644 --- a/tests/test_domain.py +++ b/tests/test_domain.py @@ -136,6 +136,9 @@ def _name_of_length(length: int): "a" * 63 + ".com", # a label may start with a digit (RFC 1123) "1host.example.com", + # the limit is in octets of the encoded name, not characters: 189 characters + # here, but 225 octets once IDNA-encoded + ".".join(["ü" * 30] * 6) + ".com", ], ) def test_returns_true_on_domain_within_rfc_length_limits(value: str): @@ -152,6 +155,10 @@ def test_returns_true_on_domain_within_rfc_length_limits(value: str): ".".join(["kld8MXQh6YalMqKRbfs895gMjW5T4p2EwToPoCSThPHHbXgmXc"] * 4) + ".kld8MXQh6YalMqKRbfs895gMjW5T4p2EwToPoCSThPHHbXgmXcab", "a" * 64 + ".com", + # fewer than 253 characters (220), but 262 octets once IDNA-encoded + ".".join(["ü" * 30] * 7) + ".com", + # the example from #407 (261 characters) + "www." + ".".join(["abcdefghijklmnop"] * 15) + ".fr", # a label must not start or end with a hyphen "-host.example.com", "host-.example.com", diff --git a/tests/test_hostname.py b/tests/test_hostname.py index 90dada65..1fe24686 100644 --- a/tests/test_hostname.py +++ b/tests/test_hostname.py @@ -81,6 +81,8 @@ def test_returns_failed_validation_on_invalid_hostname(value: str, rfc_1034: boo "a" * 63 + ".com", # a label may start with a digit (RFC 1123) "1host.example.com", + # the limit is in octets of the encoded name, not characters + ".".join(["ü" * 30] * 6) + ".com", ], ) def test_returns_true_on_hostname_within_rfc_length_limits(value: str): @@ -96,6 +98,8 @@ def test_returns_true_on_hostname_within_rfc_length_limits(value: str): + ".kld8MXQh6YalMqKRbfs895gMjW5T4p2EwToPoCSThPHHbXgmXcab", ".".join(["a" * 63, "a" * 63, "a" * 63, "a" * 62]), "a" * 64 + ".com", + # fewer than 253 characters (220), but 262 octets once IDNA-encoded + ".".join(["ü" * 30] * 7) + ".com", # a label must not start or end with a hyphen, nor contain an underscore "-host.example.com", "host-.example.com",