source: uri/tests/test_uri.py@ 605

Last change on this file since 605 was 230, checked in by wouter, 4 years ago

#91 clone https://pypi.org/project/rfc3986/

File size: 13.4 KB
RevLine 
[230]1# -*- coding: utf-8 -*-
2import pytest
3
4from rfc3986.exceptions import InvalidAuthority, ResolutionError
5from rfc3986.misc import URI_MATCHER
6from rfc3986.uri import URIReference
7
8from . import base
9
10
11@pytest.fixture
12def scheme_and_path_uri():
13 return "mailto:user@example.com"
14
15
16class TestURIReferenceParsesURIs(base.BaseTestParsesURIs):
17 """Tests for URIReference handling of URIs."""
18
19 test_class = URIReference
20
21 def test_authority_info_raises_InvalidAuthority(self, invalid_uri):
22 """Test that an invalid IPv6 is caught by authority_info()."""
23 uri = URIReference.from_string(invalid_uri)
24 with pytest.raises(InvalidAuthority):
25 uri.authority_info()
26
27 def test_attributes_catch_InvalidAuthority(self, invalid_uri):
28 """Test that an invalid IPv6 is caught by authority_info()."""
29 uri = URIReference.from_string(invalid_uri)
30 assert uri.host is None
31 assert uri.userinfo is None
32 assert uri.port is None
33
34 def test_handles_absolute_path_uri(self, absolute_path_uri):
35 """Test that URIReference can handle a path-only URI."""
36 uri = URIReference.from_string(absolute_path_uri)
37 assert uri.path == absolute_path_uri
38 assert uri.authority_info() == {
39 "userinfo": None,
40 "host": None,
41 "port": None,
42 }
43
44 def test_scheme_and_path_uri_is_valid(self, scheme_and_path_uri):
45 uri = self.test_class.from_string(scheme_and_path_uri)
46 assert uri.is_valid() is True
47
48 def test_handles_scheme_and_path_uri(self, scheme_and_path_uri):
49 """Test that self.test_class can handle a `scheme:path` URI."""
50 uri = self.test_class.from_string(scheme_and_path_uri)
51 assert uri.path == "user@example.com"
52 assert uri.scheme == "mailto"
53 assert uri.query is None
54 assert uri.host is None
55 assert uri.port is None
56 assert uri.userinfo is None
57 assert uri.authority is None
58
59 def test_parses_ipv6_to_path(self):
60 """Verify that we don't parse [ as a scheme."""
61 uri = self.test_class.from_string("[::1]")
62 assert uri.scheme is None
63 assert uri.authority is None
64 assert uri.path == "[::1]"
65
66
67class TestURIValidation:
68 # Valid URI tests
69 def test_basic_uri_is_valid(self, basic_uri):
70 uri = URIReference.from_string(basic_uri)
71 assert uri.is_valid() is True
72
73 def test_basic_uri_requiring_scheme(self, basic_uri):
74 uri = URIReference.from_string(basic_uri)
75 assert uri.is_valid(require_scheme=True) is True
76
77 def test_basic_uri_requiring_authority(self, basic_uri):
78 uri = URIReference.from_string(basic_uri)
79 assert uri.is_valid(require_authority=True) is True
80
81 def test_uri_with_everything_requiring_path(self, uri_with_everything):
82 uri = URIReference.from_string(uri_with_everything)
83 assert uri.is_valid(require_path=True) is True
84
85 def test_uri_with_everything_requiring_query(self, uri_with_everything):
86 uri = URIReference.from_string(uri_with_everything)
87 assert uri.is_valid(require_query=True) is True
88
89 def test_uri_with_everything_requiring_fragment(
90 self, uri_with_everything
91 ):
92 uri = URIReference.from_string(uri_with_everything)
93 assert uri.is_valid(require_fragment=True) is True
94
95 def test_basic_uri_with_port_is_valid(self, basic_uri_with_port):
96 uri = URIReference.from_string(basic_uri_with_port)
97 assert uri.is_valid() is True
98
99 def test_uri_with_port_and_userinfo_is_valid(
100 self, uri_with_port_and_userinfo
101 ):
102 uri = URIReference.from_string(uri_with_port_and_userinfo)
103 assert uri.is_valid() is True
104
105 def test_basic_uri_with_path_is_valid(self, basic_uri_with_path):
106 uri = URIReference.from_string(basic_uri_with_path)
107 assert uri.is_valid() is True
108
109 def test_uri_with_path_and_query_is_valid(self, uri_with_path_and_query):
110 uri = URIReference.from_string(uri_with_path_and_query)
111 assert uri.is_valid() is True
112
113 def test_uri_with_everything_is_valid(self, uri_with_everything):
114 uri = URIReference.from_string(uri_with_everything)
115 assert uri.is_valid() is True
116
117 def test_relative_uri_is_valid(self, relative_uri):
118 uri = URIReference.from_string(relative_uri)
119 assert uri.is_valid() is True
120
121 def test_absolute_path_uri_is_valid(self, absolute_path_uri):
122 uri = URIReference.from_string(absolute_path_uri)
123 assert uri.is_valid() is True
124
125 def test_scheme_and_path_uri_is_valid(self, scheme_and_path_uri):
126 uri = URIReference.from_string(scheme_and_path_uri)
127 assert uri.is_valid() is True
128
129 # Invalid URI tests
130 def test_invalid_uri_is_not_valid(self, invalid_uri):
131 uri = URIReference.from_string(invalid_uri)
132 assert uri.is_valid() is False
133
134 def test_invalid_scheme(self):
135 uri = URIReference("123", None, None, None, None)
136 assert uri.is_valid() is False
137
138 def test_invalid_path(self):
139 uri = URIReference(None, None, "foo#bar", None, None)
140 assert uri.is_valid() is False
141
142 def test_invalid_query_component(self):
143 uri = URIReference(None, None, None, "foo#bar", None)
144 assert uri.is_valid() is False
145
146 def test_invalid_fragment_component(self):
147 uri = URIReference(None, None, None, None, "foo#bar")
148 assert uri.is_valid() is False
149
150
151class TestURIReferenceUnsplits(base.BaseTestUnsplits):
152 test_class = URIReference
153
154 def test_scheme_and_path_uri_unsplits(self, scheme_and_path_uri):
155 uri = self.test_class.from_string(scheme_and_path_uri)
156 assert uri.unsplit() == scheme_and_path_uri
157
158
159class TestURIReferenceComparesToStrings:
160 def test_basic_uri(self, basic_uri):
161 uri = URIReference.from_string(basic_uri)
162 assert uri == basic_uri
163
164 def test_basic_uri_with_port(self, basic_uri_with_port):
165 uri = URIReference.from_string(basic_uri_with_port)
166 assert uri == basic_uri_with_port
167
168 def test_uri_with_port_and_userinfo(self, uri_with_port_and_userinfo):
169 uri = URIReference.from_string(uri_with_port_and_userinfo)
170 assert uri == uri_with_port_and_userinfo
171
172 def test_basic_uri_with_path(self, basic_uri_with_path):
173 uri = URIReference.from_string(basic_uri_with_path)
174 assert uri == basic_uri_with_path
175
176 def test_uri_with_path_and_query(self, uri_with_path_and_query):
177 uri = URIReference.from_string(uri_with_path_and_query)
178 assert uri == uri_with_path_and_query
179
180 def test_uri_with_everything(self, uri_with_everything):
181 uri = URIReference.from_string(uri_with_everything)
182 assert uri == uri_with_everything
183
184 def test_relative_uri(self, relative_uri):
185 uri = URIReference.from_string(relative_uri)
186 assert uri == relative_uri
187
188 def test_absolute_path_uri(self, absolute_path_uri):
189 uri = URIReference.from_string(absolute_path_uri)
190 assert uri == absolute_path_uri
191
192 def test_scheme_and_path_uri(self, scheme_and_path_uri):
193 uri = URIReference.from_string(scheme_and_path_uri)
194 assert uri == scheme_and_path_uri
195
196
197class TestURIReferenceComparesToTuples:
198 def to_tuple(self, uri):
199 return URI_MATCHER.match(uri).groups()
200
201 def test_basic_uri(self, basic_uri):
202 uri = URIReference.from_string(basic_uri)
203 assert uri == self.to_tuple(basic_uri)
204
205 def test_basic_uri_with_port(self, basic_uri_with_port):
206 uri = URIReference.from_string(basic_uri_with_port)
207 assert uri == self.to_tuple(basic_uri_with_port)
208
209 def test_uri_with_port_and_userinfo(self, uri_with_port_and_userinfo):
210 uri = URIReference.from_string(uri_with_port_and_userinfo)
211 assert uri == self.to_tuple(uri_with_port_and_userinfo)
212
213 def test_basic_uri_with_path(self, basic_uri_with_path):
214 uri = URIReference.from_string(basic_uri_with_path)
215 assert uri == self.to_tuple(basic_uri_with_path)
216
217 def test_uri_with_path_and_query(self, uri_with_path_and_query):
218 uri = URIReference.from_string(uri_with_path_and_query)
219 assert uri == self.to_tuple(uri_with_path_and_query)
220
221 def test_uri_with_everything(self, uri_with_everything):
222 uri = URIReference.from_string(uri_with_everything)
223 assert uri == self.to_tuple(uri_with_everything)
224
225 def test_relative_uri(self, relative_uri):
226 uri = URIReference.from_string(relative_uri)
227 assert uri == self.to_tuple(relative_uri)
228
229 def test_absolute_path_uri(self, absolute_path_uri):
230 uri = URIReference.from_string(absolute_path_uri)
231 assert uri == self.to_tuple(absolute_path_uri)
232
233 def test_scheme_and_path_uri(self, scheme_and_path_uri):
234 uri = URIReference.from_string(scheme_and_path_uri)
235 assert uri == self.to_tuple(scheme_and_path_uri)
236
237
238def test_uri_comparison_raises_TypeError(basic_uri):
239 uri = URIReference.from_string(basic_uri)
240 with pytest.raises(TypeError):
241 uri == 1
242
243
244class TestURIReferenceComparesToURIReferences:
245 def test_same_basic_uri(self, basic_uri):
246 uri = URIReference.from_string(basic_uri)
247 assert uri == uri
248
249 def test_different_basic_uris(self, basic_uri, basic_uri_with_port):
250 uri = URIReference.from_string(basic_uri)
251 assert (uri == URIReference.from_string(basic_uri_with_port)) is False
252
253
254class TestURIReferenceIsAbsolute:
255 def test_basic_uris_are_absolute(self, basic_uri):
256 uri = URIReference.from_string(basic_uri)
257 assert uri.is_absolute() is True
258
259 def test_basic_uris_with_ports_are_absolute(self, basic_uri_with_port):
260 uri = URIReference.from_string(basic_uri_with_port)
261 assert uri.is_absolute() is True
262
263 def test_basic_uris_with_paths_are_absolute(self, basic_uri_with_path):
264 uri = URIReference.from_string(basic_uri_with_path)
265 assert uri.is_absolute() is True
266
267 def test_uri_with_everything_are_not_absolute(self, uri_with_everything):
268 uri = URIReference.from_string(uri_with_everything)
269 assert uri.is_absolute() is False
270
271 def test_absolute_paths_are_not_absolute_uris(self, absolute_path_uri):
272 uri = URIReference.from_string(absolute_path_uri)
273 assert uri.is_absolute() is False
274
275
276# @pytest.fixture(params=[
277# basic_uri, basic_uri_with_port, basic_uri_with_path,
278# scheme_and_path_uri, uri_with_path_and_query
279# ])
280# @pytest.fixture(params=[absolute_path_uri, relative_uri])
281
282
283class TestURIReferencesResolve:
284 def test_with_basic_and_relative_uris(self, basic_uri, relative_uri):
285 R = URIReference.from_string(relative_uri)
286 B = URIReference.from_string(basic_uri)
287 T = R.resolve_with(basic_uri)
288 assert T.scheme == B.scheme
289 assert T.host == R.host
290 assert T.path == R.path
291
292 def test_with_basic_and_absolute_path_uris(
293 self, basic_uri, absolute_path_uri
294 ):
295 R = URIReference.from_string(absolute_path_uri)
296 B = URIReference.from_string(basic_uri).normalize()
297 T = R.resolve_with(B)
298 assert T.scheme == B.scheme
299 assert T.host == B.host
300 assert T.path == R.path
301
302 def test_with_basic_uri_and_relative_path(self, basic_uri):
303 R = URIReference.from_string("foo/bar/bogus")
304 B = URIReference.from_string(basic_uri).normalize()
305 T = R.resolve_with(B)
306 assert T.scheme == B.scheme
307 assert T.host == B.host
308 assert T.path == "/" + R.path
309
310 def test_basic_uri_with_path_and_relative_path(self, basic_uri_with_path):
311 R = URIReference.from_string("foo/bar/bogus")
312 B = URIReference.from_string(basic_uri_with_path).normalize()
313 T = R.resolve_with(B)
314 assert T.scheme == B.scheme
315 assert T.host == B.host
316
317 index = B.path.rfind("/")
318 assert T.path == B.path[:index] + "/" + R.path
319
320 def test_uri_with_everything_raises_exception(self, uri_with_everything):
321 R = URIReference.from_string("foo/bar/bogus")
322 B = URIReference.from_string(uri_with_everything)
323 with pytest.raises(ResolutionError):
324 R.resolve_with(B)
325
326 def test_basic_uri_resolves_itself(self, basic_uri):
327 R = URIReference.from_string(basic_uri)
328 B = URIReference.from_string(basic_uri)
329 T = R.resolve_with(B)
330 assert T == B
331
332 def test_differing_schemes(self, basic_uri):
333 R = URIReference.from_string("https://example.com/path")
334 B = URIReference.from_string(basic_uri)
335 T = R.resolve_with(B)
336 assert T.scheme == R.scheme
337
338 def test_resolve_pathless_fragment(self, basic_uri):
339 R = URIReference.from_string("#fragment")
340 B = URIReference.from_string(basic_uri)
341 T = R.resolve_with(B)
342 assert T.path is None
343 assert T.fragment == "fragment"
344
345 def test_resolve_pathless_query(self, basic_uri):
346 R = URIReference.from_string("?query")
347 B = URIReference.from_string(basic_uri)
348 T = R.resolve_with(B)
349 assert T.path is None
350 assert T.query == "query"
351
352
353def test_empty_querystrings_persist():
354 url = "https://httpbin.org/get?"
355 ref = URIReference.from_string(url)
356 assert ref.query == ""
357 assert ref.unsplit() == url
358
359
360def test_wide_domain_bypass_check():
361 """Verify we properly parse/handle the authority.
362
363 See also:
364 https://bugs.xdavidhu.me/google/2020/03/08/the-unexpected-google-wide-domain-check-bypass/
365 """
366 url = "https://user:pass@xdavidhu.me\\test.corp.google.com:8080/path/to/something?param=value#hash"
367 ref = URIReference.from_string(url)
368 assert ref.scheme == "https"
369 assert ref.host == "xdavidhu.me"
Note: See TracBrowser for help on using the repository browser.