Repository navigation
Expand file tree
/
Copy pathtest_hostname.py
More file actions
199 lines (173 loc) · 7.04 KB
/
Copy pathtest_hostname.py
File metadata and controls
199 lines (173 loc) · 7.04 KB
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
"""Test Hostname."""
# external
import pytest
# local
from validators import ValidationError, hostname
@pytest.mark.parametrize(
("value", "rfc_1034", "rfc_2782"),
[
# simple hostname w/ optional ports
("ubuntu-pc:443", False, False),
("this-pc", False, False),
("lab-01a-notebook:404", False, False),
("4-oh-4", False, False),
# simple, single-label hostname w/ trailing dot (RFC 1034); see #442
("this-pc.", True, False),
("ie.", True, False),
# hostname w/ optional ports
("example.com:4444", False, False),
("kräuter.com.", True, False),
("xn----gtbspbbmkef.xn--p1ai:65535", False, False),
("_example.com", False, True),
# ipv4 addr w/ optional ports
("123.123.123.123:9090", False, False),
("127.0.0.1:43512", False, False),
("123.5.77.88:31000", False, False),
("12.12.12.12:5353", False, False),
# ipv6 addr w/ optional ports
("[::1]:22", False, False),
("[dead:beef:0:0:0:0000:42:1]:5731", False, False),
("[0:0:0:0:0:ffff:1.2.3.4]:80", False, False),
("[0:a:b:c:d:e:f::]:53", False, False),
],
)
def test_returns_true_on_valid_hostname(value: str, rfc_1034: bool, rfc_2782: bool):
"""Test returns true on valid hostname."""
assert hostname(value, rfc_1034=rfc_1034, rfc_2782=rfc_2782)
@pytest.mark.parametrize(
("value", "rfc_1034", "rfc_2782"),
[
# bad (simple hostname w/ optional ports)
("ubuntu-pc:443080", False, False),
("this-pc-is-sh*t", False, False),
("lab-01a-note._com_.com:404", False, False),
("4-oh-4:@.com", False, False),
# trailing dot is only allowed with rfc_1034; see #442
("this-pc.", False, False),
# bad (hostname w/ optional ports)
("example.com:-4444", False, False),
("xn----gtbspbbmkef.xn--p1ai:65538", False, False),
("_example.com:0", False, True),
("kräuter.com.:81_00", True, False),
# bad (ipv4 addr w/ optional ports)
("123.123.123.123:99999", False, False),
("127.0.0.1:", False, False),
("123.5.-12.88:8080", False, False),
("12.12.12.12:$#", False, False),
# bad (ipv6 addr w/ optional ports)
("[::1]:[22]", False, False),
("[dead:beef:0:-:0:-:42:1]:5731", False, False),
("[0:0:0:0:0:ffff:1.2.3.4]:-65538", False, False),
("[0:&:b:c:@:e:f:::9999", False, False),
],
)
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",
# 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):
"""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",
# 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",
"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)
@pytest.mark.parametrize(
"value",
[
"ubuntu-pc\n",
"ubuntu-pc:443\n",
"example.com:443\n",
"127.0.0.1:22\n",
"[::1]:22\n",
"[dead:beef:0:0:0:0000:42:1]:5731\n",
],
)
def test_rejects_trailing_newline_in_hostnames_and_ports(value: str):
"""Test rejects trailing newline in hostnames and ports."""
assert isinstance(hostname(value), ValidationError)
@pytest.mark.parametrize(
"value", ["\u017ferver", "\u212aelvin", "\u0131ntranet", "\u0130ntranet:8080"]
)
def test_returns_failed_validation_on_non_ascii_simple_hostname(value: str):
"""Test returns failed validation on non-ASCII case equivalents in simple hostnames."""
assert isinstance(hostname(value), ValidationError)
@pytest.mark.parametrize("value", ["example.\uff43\uff4f\uff4d", "exam\u00adple.com:443"])
def test_returns_failed_validation_on_idna_mapped_lookalike_hostname(value: str):
"""Test returns failed validation on hostnames that only IDNA 2003 mapping makes valid."""
assert isinstance(hostname(value), ValidationError)
@pytest.mark.parametrize("value", ["10.0.0.\u0661", "123.5.77.\u06688:31000"])
def test_returns_failed_validation_on_ipv4_lookalike_hostname(value: str):
"""Test returns failed validation on dotted names whose last label is non-ASCII digits."""
assert isinstance(hostname(value), ValidationError)
@pytest.mark.parametrize(
"value",
[
"example.com:443",
"xn--e1afmkfd.xn--p1ai",
"пример.рф",
"пример.рф:8080",
],
)
def test_returns_true_on_valid_top_level_domain_hostname(value: str):
"""Test returns true on hostname with a TLD allowed by IANA."""
assert hostname(value, consider_tld=True)
@pytest.mark.parametrize(
"value",
[
"example.flat:443",
"пример.рфы",
],
)
def test_returns_failed_validation_on_invalid_top_level_domain_hostname(value: str):
"""Test returns failed validation on hostname with a TLD not allowed by IANA."""
assert isinstance(hostname(value, consider_tld=True), ValidationError)
@pytest.mark.parametrize(
"value",
[
# ref: RFC 3986 (3.2.2), only an IPv6 address is enclosed in brackets
"[1.2.3.4]:80",
"[example.com]:80",
"[localhost]:80",
# exactly one pair of brackets
"[[::1]]:80",
"[[::1]:80",
"[::1]]:80",
"::1]:80",
"localhost]:80",
"[::1%]]:80",
],
)
def test_returns_failed_validation_on_malformed_bracketed_host(value: str):
"""Test returns failed validation on brackets that do not enclose one IPv6 address."""
assert isinstance(hostname(value), ValidationError)
def test_returns_failed_validation_on_bracketed_ipv6_when_skipped():
"""Test returns failed validation on a bracketed IPv6 address when IPv6 is skipped."""
assert isinstance(hostname("[::1]:80", skip_ipv6_addr=True), ValidationError)