summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/conftest.py4
-rw-r--r--tests/test_api.py16
-rw-r--r--tests/test_normalizers.py72
-rw-r--r--tests/test_unicode_support.py26
-rw-r--r--tests/test_uri.py408
5 files changed, 526 insertions, 0 deletions
diff --git a/tests/conftest.py b/tests/conftest.py
new file mode 100644
index 0000000..ba44dad
--- /dev/null
+++ b/tests/conftest.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8 -*-
+import sys
+
+sys.path.insert(0, '.')
diff --git a/tests/test_api.py b/tests/test_api.py
new file mode 100644
index 0000000..9e9189a
--- /dev/null
+++ b/tests/test_api.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+from rfc3986.api import (
+ uri_reference, is_valid_uri, normalize_uri, URIReference
+ )
+
+
+def test_uri_reference():
+ assert isinstance(uri_reference('http://example.com'), URIReference)
+
+
+def test_is_valid_uri():
+ assert is_valid_uri('http://example.com') is True
+
+
+def test_normalize_uri():
+ assert normalize_uri('HTTP://EXAMPLE.COM') == 'http://example.com'
diff --git a/tests/test_normalizers.py b/tests/test_normalizers.py
new file mode 100644
index 0000000..ddcb97b
--- /dev/null
+++ b/tests/test_normalizers.py
@@ -0,0 +1,72 @@
+# -*- coding: utf-8 -*-
+import pytest
+
+from rfc3986.uri import URIReference
+from rfc3986.normalizers import (
+ normalize_scheme, normalize_percent_characters, remove_dot_segments
+ )
+
+
+def test_normalize_scheme():
+ assert 'http' == normalize_scheme('htTp')
+ assert 'http' == normalize_scheme('http')
+ assert 'http' == normalize_scheme('HTTP')
+
+
+def test_normalize_percent_characters():
+ expected = '%3Athis_should_be_lowercase%DF%AB%4C'
+ assert expected == normalize_percent_characters(
+ '%3athis_should_be_lowercase%DF%ab%4c')
+ assert expected == normalize_percent_characters(
+ '%3Athis_should_be_lowercase%DF%AB%4C')
+ assert expected == normalize_percent_characters(
+ '%3Athis_should_be_lowercase%DF%aB%4C')
+
+
+paths = [
+ # (Input, expected output)
+ ('/foo/bar/.', '/foo/bar/'),
+ ('/foo/bar/', '/foo/bar/'),
+ ('/foo/bar', '/foo/bar'),
+ ('./foo/bar', 'foo/bar'),
+ ('/./foo/bar', '/foo/bar'),
+ ('/foo%20bar/biz%2Abaz', '/foo%20bar/biz%2Abaz'),
+ ('../foo/bar', 'foo/bar'),
+ ('/../foo/bar', '/foo/bar'),
+ ('a/./b/../b/%63/%7Bfoo%7D', 'a/b/%63/%7Bfoo%7D'),
+ ('//a/./b/../b/%63/%7Bfoo%7D', '//a/b/%63/%7Bfoo%7D'),
+ ('mid/content=5/../6', 'mid/6'),
+ ('/a/b/c/./../../g', '/a/g'),
+ ]
+
+
+@pytest.fixture(params=paths)
+def path_fixture(request):
+ return request.param
+
+
+@pytest.fixture(params=paths)
+def uris(request):
+ to_norm, normalized = request.param
+ return (URIReference(None, None, to_norm, None, None),
+ URIReference(None, None, normalized, None, None))
+
+
+def test_remove_dot_segments(path_fixture):
+ to_normalize, expected = path_fixture
+ assert expected == remove_dot_segments(to_normalize)
+
+
+def test_normalized_equality(uris):
+ assert uris[0] == uris[1]
+
+
+def test_hostname_normalization():
+ assert (URIReference(None, 'EXAMPLE.COM', None, None, None) ==
+ URIReference(None, 'example.com', None, None, None))
+
+
+def test_authority_normalization():
+ uri = URIReference(
+ None, 'user%2aName@EXAMPLE.COM', None, None, None).normalize()
+ assert uri.authority == 'user%2AName@example.com'
diff --git a/tests/test_unicode_support.py b/tests/test_unicode_support.py
new file mode 100644
index 0000000..0d6ea86
--- /dev/null
+++ b/tests/test_unicode_support.py
@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+
+from rfc3986 import uri_reference
+
+
+def test_unicode_uri():
+ url_bytestring = b'http://example.com?utf8=\xe2\x98\x83'
+ unicode_url = url_bytestring.decode('utf-8')
+ uri = uri_reference(unicode_url)
+ assert uri.is_valid() is True
+ assert uri == 'http://example.com?utf8=%E2%98%83'
+
+
+def test_unicode_uri_passed_as_bytes():
+ url_bytestring = b'http://example.com?utf8=\xe2\x98\x83'
+ uri = uri_reference(url_bytestring)
+ assert uri.is_valid() is True
+ assert uri == 'http://example.com?utf8=%E2%98%83'
+
+
+def test_unicode_authority():
+ url_bytestring = b'http://\xe2\x98\x83.com'
+ unicode_url = url_bytestring.decode('utf-8')
+ uri = uri_reference(unicode_url)
+ assert uri.is_valid() is False
+ assert uri == unicode_url
diff --git a/tests/test_uri.py b/tests/test_uri.py
new file mode 100644
index 0000000..8817a54
--- /dev/null
+++ b/tests/test_uri.py
@@ -0,0 +1,408 @@
+# -*- coding: utf-8 -*-
+import pytest
+
+from rfc3986.exceptions import InvalidAuthority
+from rfc3986.misc import URI_MATCHER
+from rfc3986.uri import URIReference
+
+
+valid_hosts = [
+ '[21DA:00D3:0000:2F3B:02AA:00FF:FE28:9C5A]', '[::1]',
+ '[21DA:D3:0:2F3B:2AA:FF:FE28:9C5A]', '[FE80::2AA:FF:FE9A:4CA2]',
+ '[FF02::2]', '[FF02:3::5]', '[FF02:0:0:0:0:0:0:2]',
+ '[FF02:30:0:0:0:0:0:5]', '127.0.0.1', 'www.example.com', 'localhost'
+ ]
+
+invalid_hosts = [
+ '[FF02::3::5]', # IPv6 can only have one ::
+ '[FADF:01]', # Not properly compacted (missing a :)
+ 'localhost:80:80:80' # Too many ports
+ ]
+
+
+@pytest.fixture(params=valid_hosts)
+def basic_uri(request):
+ return 'http://%s' % request.param
+
+
+@pytest.fixture(params=valid_hosts)
+def basic_uri_with_port(request):
+ return 'ftp://%s:21' % request.param
+
+
+@pytest.fixture(params=valid_hosts)
+def uri_with_port_and_userinfo(request):
+ return 'ssh://user:pass@%s:22' % request.param
+
+
+@pytest.fixture(params=valid_hosts)
+def basic_uri_with_path(request):
+ return 'http://%s/path/to/resource' % request.param
+
+
+@pytest.fixture(params=valid_hosts)
+def uri_with_path_and_query(request):
+ return 'http://%s/path/to/resource?key=value' % request.param
+
+
+@pytest.fixture(params=valid_hosts)
+def uri_with_everything(request):
+ return 'https://user:pass@%s:443/path/to/resource?key=value#fragment' % (
+ request.param)
+
+
+@pytest.fixture(params=valid_hosts)
+def relative_uri(request):
+ return '//%s' % request.param
+
+
+@pytest.fixture
+def absolute_path_uri():
+ return '/path/to/file'
+
+
+@pytest.fixture(params=invalid_hosts)
+def invalid_uri(request):
+ return 'https://%s' % request.param
+
+
+@pytest.fixture
+def scheme_and_path_uri():
+ return 'mailto:user@example.com'
+
+
+class TestURIReferenceParsesURIs:
+ """Tests for URIReference handling of URIs."""
+ def test_handles_basic_uri(self, basic_uri):
+ """Test that URIReference can handle a simple URI."""
+ uri = URIReference.from_string(basic_uri)
+ assert uri.scheme == 'http'
+ assert uri.authority == basic_uri[7:] # len('http://')
+ assert uri.host == uri.authority
+ assert uri.path is None
+ assert uri.query is None
+ assert uri.fragment is None
+ assert uri.port is None
+ assert uri.userinfo is None
+
+ def test_handles_basic_uri_with_port(self, basic_uri_with_port):
+ """Test that URIReference can handle a simple URI with a port."""
+ uri = URIReference.from_string(basic_uri_with_port)
+ assert uri.scheme == 'ftp'
+ assert uri.authority == basic_uri_with_port[6:] # len('ftp://')
+ assert uri.host != uri.authority
+ assert uri.port == '21'
+ assert uri.path is None
+ assert uri.query is None
+ assert uri.fragment is None
+ assert uri.userinfo is None
+
+ def test_handles_uri_with_port_and_userinfo(
+ self, uri_with_port_and_userinfo):
+ """
+ Test that URIReference can handle a URI with a port and userinfo.
+ """
+ uri = URIReference.from_string(uri_with_port_and_userinfo)
+ assert uri.scheme == 'ssh'
+ # 6 == len('ftp://')
+ assert uri.authority == uri_with_port_and_userinfo[6:]
+ assert uri.host != uri.authority
+ assert uri.port == '22'
+ assert uri.path is None
+ assert uri.query is None
+ assert uri.fragment is None
+ assert uri.userinfo == 'user:pass'
+
+ def test_handles_basic_uri_with_path(self, basic_uri_with_path):
+ """Test that URIReference can handle a URI with a path."""
+ uri = URIReference.from_string(basic_uri_with_path)
+ assert uri.scheme == 'http'
+ assert basic_uri_with_path == (uri.scheme + '://' + uri.authority
+ + uri.path)
+ assert uri.host == uri.authority
+ assert uri.path == '/path/to/resource'
+ assert uri.query is None
+ assert uri.fragment is None
+ assert uri.userinfo is None
+ assert uri.port is None
+
+ def test_handles_uri_with_path_and_query(self, uri_with_path_and_query):
+ """
+ Test that URIReference can handle a URI with a path and query.
+ """
+ uri = URIReference.from_string(uri_with_path_and_query)
+ assert uri.scheme == 'http'
+ assert uri.host == uri.authority
+ assert uri.path == '/path/to/resource'
+ assert uri.query == 'key=value'
+ assert uri.fragment is None
+ assert uri.userinfo is None
+ assert uri.port is None
+
+ def test_handles_uri_with_everything(self, uri_with_everything):
+ """
+ Test that URIReference can handle and with everything in it.
+ """
+ uri = URIReference.from_string(uri_with_everything)
+ assert uri.scheme == 'https'
+ assert uri.path == '/path/to/resource'
+ assert uri.query == 'key=value'
+ assert uri.fragment == 'fragment'
+ assert uri.userinfo == 'user:pass'
+ assert uri.port == '443'
+
+ def test_authority_info_raises_InvalidAuthority(self, invalid_uri):
+ """Test that an invalid IPv6 is caught by authority_info()."""
+ uri = URIReference.from_string(invalid_uri)
+ with pytest.raises(InvalidAuthority):
+ uri.authority_info()
+
+ def test_attributes_catch_InvalidAuthority(self, invalid_uri):
+ """Test that an invalid IPv6 is caught by authority_info()."""
+ uri = URIReference.from_string(invalid_uri)
+ assert uri.host is None
+ assert uri.userinfo is None
+ assert uri.port is None
+
+ def test_handles_relative_uri(self, relative_uri):
+ """Test that URIReference can handle a relative URI."""
+ uri = URIReference.from_string(relative_uri)
+ assert uri.scheme is None
+ assert uri.authority == relative_uri[2:]
+
+ def test_handles_absolute_path_uri(self, absolute_path_uri):
+ """Test that URIReference can handle a path-only URI."""
+ uri = URIReference.from_string(absolute_path_uri)
+ assert uri.path == absolute_path_uri
+ assert uri.authority_info() == {
+ 'userinfo': None,
+ 'host': None,
+ 'port': None,
+ }
+
+ def test_handles_scheme_and_path_uri(self, scheme_and_path_uri):
+ """Test that URIReference can handle a `scheme:path` URI."""
+ uri = URIReference.from_string(scheme_and_path_uri)
+ assert uri.path == 'user@example.com'
+ assert uri.scheme == 'mailto'
+ assert uri.query is None
+ assert uri.host is None
+ assert uri.port is None
+ assert uri.userinfo is None
+ assert uri.authority is None
+
+
+class TestURIValidation:
+ # Valid URI tests
+ def test_basic_uri_is_valid(self, basic_uri):
+ uri = URIReference.from_string(basic_uri)
+ assert uri.is_valid() is True
+
+ def test_basic_uri_requiring_scheme(self, basic_uri):
+ uri = URIReference.from_string(basic_uri)
+ assert uri.is_valid(require_scheme=True) is True
+
+ def test_basic_uri_requiring_authority(self, basic_uri):
+ uri = URIReference.from_string(basic_uri)
+ assert uri.is_valid(require_authority=True) is True
+
+ def test_uri_with_everything_requiring_path(self, uri_with_everything):
+ uri = URIReference.from_string(uri_with_everything)
+ assert uri.is_valid(require_path=True) is True
+
+ def test_uri_with_everything_requiring_query(self, uri_with_everything):
+ uri = URIReference.from_string(uri_with_everything)
+ assert uri.is_valid(require_query=True) is True
+
+ def test_uri_with_everything_requiring_fragment(self,
+ uri_with_everything):
+ uri = URIReference.from_string(uri_with_everything)
+ assert uri.is_valid(require_fragment=True) is True
+
+ def test_basic_uri_with_port_is_valid(self, basic_uri_with_port):
+ uri = URIReference.from_string(basic_uri_with_port)
+ assert uri.is_valid() is True
+
+ def test_uri_with_port_and_userinfo_is_valid(self,
+ uri_with_port_and_userinfo):
+ uri = URIReference.from_string(uri_with_port_and_userinfo)
+ assert uri.is_valid() is True
+
+ def test_basic_uri_with_path_is_valid(self, basic_uri_with_path):
+ uri = URIReference.from_string(basic_uri_with_path)
+ assert uri.is_valid() is True
+
+ def test_uri_with_path_and_query_is_valid(self, uri_with_path_and_query):
+ uri = URIReference.from_string(uri_with_path_and_query)
+ assert uri.is_valid() is True
+
+ def test_uri_with_everything_is_valid(self, uri_with_everything):
+ uri = URIReference.from_string(uri_with_everything)
+ assert uri.is_valid() is True
+
+ def test_relative_uri_is_valid(self, relative_uri):
+ uri = URIReference.from_string(relative_uri)
+ assert uri.is_valid() is True
+
+ def test_absolute_path_uri_is_valid(self, absolute_path_uri):
+ uri = URIReference.from_string(absolute_path_uri)
+ assert uri.is_valid() is True
+
+ def test_scheme_and_path_uri_is_valid(self, scheme_and_path_uri):
+ uri = URIReference.from_string(scheme_and_path_uri)
+ assert uri.is_valid() is True
+
+ # Invalid URI tests
+ def test_invalid_uri_is_not_valid(self, invalid_uri):
+ uri = URIReference.from_string(invalid_uri)
+ assert uri.is_valid() is False
+
+ def test_invalid_scheme(self):
+ uri = URIReference('123', None, None, None, None)
+ assert uri.is_valid() is False
+
+ def test_invalid_path(self):
+ uri = URIReference(None, None, 'foo#bar', None, None)
+ assert uri.is_valid() is False
+
+ def test_invalid_query_component(self):
+ uri = URIReference(None, None, None, 'foo#bar', None)
+ assert uri.is_valid() is False
+
+ def test_invalid_fragment_component(self):
+ uri = URIReference(None, None, None, None, 'foo#bar')
+ assert uri.is_valid() is False
+
+
+class TestURIReferenceUnsplits:
+ def test_basic_uri_unsplits(self, basic_uri):
+ uri = URIReference.from_string(basic_uri)
+ assert uri.unsplit() == basic_uri
+
+ def test_basic_uri_with_port_unsplits(self, basic_uri_with_port):
+ uri = URIReference.from_string(basic_uri_with_port)
+ assert uri.unsplit() == basic_uri_with_port
+
+ def test_uri_with_port_and_userinfo_unsplits(self,
+ uri_with_port_and_userinfo):
+ uri = URIReference.from_string(uri_with_port_and_userinfo)
+ assert uri.unsplit() == uri_with_port_and_userinfo
+
+ def test_basic_uri_with_path_unsplits(self, basic_uri_with_path):
+ uri = URIReference.from_string(basic_uri_with_path)
+ assert uri.unsplit() == basic_uri_with_path
+
+ def test_uri_with_path_and_query_unsplits(self, uri_with_path_and_query):
+ uri = URIReference.from_string(uri_with_path_and_query)
+ assert uri.unsplit() == uri_with_path_and_query
+
+ def test_uri_with_everything_unsplits(self, uri_with_everything):
+ uri = URIReference.from_string(uri_with_everything)
+ assert uri.unsplit() == uri_with_everything
+
+ def test_relative_uri_unsplits(self, relative_uri):
+ uri = URIReference.from_string(relative_uri)
+ assert uri.unsplit() == relative_uri
+
+ def test_absolute_path_uri_unsplits(self, absolute_path_uri):
+ uri = URIReference.from_string(absolute_path_uri)
+ assert uri.unsplit() == absolute_path_uri
+
+ def test_scheme_and_path_uri_unsplits(self, scheme_and_path_uri):
+ uri = URIReference.from_string(scheme_and_path_uri)
+ assert uri.unsplit() == scheme_and_path_uri
+
+
+class TestURIReferenceComparesToStrings:
+ def test_basic_uri(self, basic_uri):
+ uri = URIReference.from_string(basic_uri)
+ assert uri == basic_uri
+
+ def test_basic_uri_with_port(self, basic_uri_with_port):
+ uri = URIReference.from_string(basic_uri_with_port)
+ assert uri == basic_uri_with_port
+
+ def test_uri_with_port_and_userinfo(self, uri_with_port_and_userinfo):
+ uri = URIReference.from_string(uri_with_port_and_userinfo)
+ assert uri == uri_with_port_and_userinfo
+
+ def test_basic_uri_with_path(self, basic_uri_with_path):
+ uri = URIReference.from_string(basic_uri_with_path)
+ assert uri == basic_uri_with_path
+
+ def test_uri_with_path_and_query(self, uri_with_path_and_query):
+ uri = URIReference.from_string(uri_with_path_and_query)
+ assert uri == uri_with_path_and_query
+
+ def test_uri_with_everything(self, uri_with_everything):
+ uri = URIReference.from_string(uri_with_everything)
+ assert uri == uri_with_everything
+
+ def test_relative_uri(self, relative_uri):
+ uri = URIReference.from_string(relative_uri)
+ assert uri == relative_uri
+
+ def test_absolute_path_uri(self, absolute_path_uri):
+ uri = URIReference.from_string(absolute_path_uri)
+ assert uri == absolute_path_uri
+
+ def test_scheme_and_path_uri(self, scheme_and_path_uri):
+ uri = URIReference.from_string(scheme_and_path_uri)
+ assert uri == scheme_and_path_uri
+
+
+class TestURIReferenceComparesToTuples:
+ def to_tuple(self, uri):
+ return URI_MATCHER.match(uri).groups()
+
+ def test_basic_uri(self, basic_uri):
+ uri = URIReference.from_string(basic_uri)
+ assert uri == self.to_tuple(basic_uri)
+
+ def test_basic_uri_with_port(self, basic_uri_with_port):
+ uri = URIReference.from_string(basic_uri_with_port)
+ assert uri == self.to_tuple(basic_uri_with_port)
+
+ def test_uri_with_port_and_userinfo(self, uri_with_port_and_userinfo):
+ uri = URIReference.from_string(uri_with_port_and_userinfo)
+ assert uri == self.to_tuple(uri_with_port_and_userinfo)
+
+ def test_basic_uri_with_path(self, basic_uri_with_path):
+ uri = URIReference.from_string(basic_uri_with_path)
+ assert uri == self.to_tuple(basic_uri_with_path)
+
+ def test_uri_with_path_and_query(self, uri_with_path_and_query):
+ uri = URIReference.from_string(uri_with_path_and_query)
+ assert uri == self.to_tuple(uri_with_path_and_query)
+
+ def test_uri_with_everything(self, uri_with_everything):
+ uri = URIReference.from_string(uri_with_everything)
+ assert uri == self.to_tuple(uri_with_everything)
+
+ def test_relative_uri(self, relative_uri):
+ uri = URIReference.from_string(relative_uri)
+ assert uri == self.to_tuple(relative_uri)
+
+ def test_absolute_path_uri(self, absolute_path_uri):
+ uri = URIReference.from_string(absolute_path_uri)
+ assert uri == self.to_tuple(absolute_path_uri)
+
+ def test_scheme_and_path_uri(self, scheme_and_path_uri):
+ uri = URIReference.from_string(scheme_and_path_uri)
+ assert uri == self.to_tuple(scheme_and_path_uri)
+
+
+def test_uri_comparison_raises_TypeError(basic_uri):
+ uri = URIReference.from_string(basic_uri)
+ with pytest.raises(TypeError):
+ uri == 1
+
+
+class TestURIReferenceComparesToURIReferences:
+ def test_same_basic_uri(self, basic_uri):
+ uri = URIReference.from_string(basic_uri)
+ assert uri == uri
+
+ def test_different_basic_uris(self, basic_uri, basic_uri_with_port):
+ uri = URIReference.from_string(basic_uri)
+ assert (uri == URIReference.from_string(basic_uri_with_port)) is False