197 lines
7.1 KiB
Python
197 lines
7.1 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""Tests for the validators module."""
|
|
import rfc3986
|
|
from rfc3986 import exceptions
|
|
from rfc3986 import validators
|
|
|
|
import pytest
|
|
|
|
|
|
def test_defaults():
|
|
"""Verify the default Validator settings."""
|
|
validator = validators.Validator()
|
|
|
|
assert validator.required_components == {
|
|
c: False for c in validator.COMPONENT_NAMES
|
|
}
|
|
assert validator.allow_password is True
|
|
assert validator.allowed_schemes == set()
|
|
assert validator.allowed_hosts == set()
|
|
assert validator.allowed_ports == set()
|
|
|
|
|
|
def test_allowing_schemes():
|
|
"""Verify the ability to select schemes to be allowed."""
|
|
validator = validators.Validator().allow_schemes('http', 'https')
|
|
|
|
assert 'http' in validator.allowed_schemes
|
|
assert 'https' in validator.allowed_schemes
|
|
|
|
|
|
def test_allowing_hosts():
|
|
"""Verify the ability to select hosts to be allowed."""
|
|
validator = validators.Validator().allow_hosts(
|
|
'pypi.python.org', 'pypi.org',
|
|
)
|
|
|
|
assert 'pypi.python.org' in validator.allowed_hosts
|
|
assert 'pypi.org' in validator.allowed_hosts
|
|
|
|
|
|
def test_allowing_ports():
|
|
"""Verify the ability select ports to be allowed."""
|
|
validator = validators.Validator().allow_ports('80', '100')
|
|
|
|
assert '80' in validator.allowed_ports
|
|
assert '100' in validator.allowed_ports
|
|
|
|
|
|
def test_requiring_invalid_component():
|
|
"""Verify that we validate required component names."""
|
|
with pytest.raises(ValueError):
|
|
validators.Validator().require_presence_of('frob')
|
|
|
|
|
|
def test_use_of_password():
|
|
"""Verify the behaviour of {forbid,allow}_use_of_password."""
|
|
validator = validators.Validator()
|
|
assert validator.allow_password is True
|
|
|
|
validator.forbid_use_of_password()
|
|
assert validator.allow_password is False
|
|
|
|
validator.allow_use_of_password()
|
|
assert validator.allow_password is True
|
|
|
|
|
|
@pytest.mark.parametrize('uri', [
|
|
rfc3986.uri_reference('https://user:password@github.com'),
|
|
rfc3986.uri_reference('https://user:password@github.com/path'),
|
|
rfc3986.uri_reference('https://user:password@github.com/path?query'),
|
|
rfc3986.uri_reference('https://user:password@github.com/path?query#frag'),
|
|
rfc3986.uri_reference('//user:password@github.com'),
|
|
])
|
|
def test_forbidden_passwords(uri):
|
|
"""Verify that passwords are disallowed."""
|
|
validator = validators.Validator().forbid_use_of_password()
|
|
with pytest.raises(exceptions.PasswordForbidden):
|
|
validator.validate(uri)
|
|
|
|
|
|
@pytest.mark.parametrize('uri', [
|
|
rfc3986.uri_reference('https://user@github.com'),
|
|
rfc3986.uri_reference('https://user@github.com/path'),
|
|
rfc3986.uri_reference('https://user@github.com/path?query'),
|
|
rfc3986.uri_reference('https://user@github.com/path?query#frag'),
|
|
rfc3986.uri_reference('//user@github.com'),
|
|
rfc3986.uri_reference('//github.com'),
|
|
rfc3986.uri_reference('https://github.com'),
|
|
])
|
|
def test_passwordless_uris_pass_validation(uri):
|
|
"""Verify password-less URLs validate properly."""
|
|
validator = validators.Validator().forbid_use_of_password()
|
|
validator.validate(uri)
|
|
|
|
|
|
@pytest.mark.parametrize('uri', [
|
|
rfc3986.uri_reference('https://'),
|
|
rfc3986.uri_reference('/path/to/resource'),
|
|
])
|
|
def test_missing_host_component(uri):
|
|
"""Verify that missing host components cause errors."""
|
|
validator = validators.Validator().require_presence_of('host')
|
|
with pytest.raises(exceptions.MissingComponentError):
|
|
validator.validate(uri)
|
|
|
|
|
|
@pytest.mark.parametrize('uri', [
|
|
rfc3986.uri_reference('https://'),
|
|
rfc3986.uri_reference('//google.com'),
|
|
rfc3986.uri_reference('//google.com?query=value'),
|
|
rfc3986.uri_reference('//google.com#fragment'),
|
|
rfc3986.uri_reference('https://google.com'),
|
|
rfc3986.uri_reference('https://google.com#fragment'),
|
|
rfc3986.uri_reference('https://google.com?query=value'),
|
|
])
|
|
def test_missing_path_component(uri):
|
|
"""Verify that missing path components cause errors."""
|
|
validator = validators.Validator().require_presence_of('path')
|
|
with pytest.raises(exceptions.MissingComponentError):
|
|
validator.validate(uri)
|
|
|
|
|
|
@pytest.mark.parametrize('uri', [
|
|
rfc3986.uri_reference('//google.com'),
|
|
rfc3986.uri_reference('//google.com?query=value'),
|
|
rfc3986.uri_reference('//google.com#fragment'),
|
|
])
|
|
def test_multiple_missing_components(uri):
|
|
"""Verify that multiple missing components are caught."""
|
|
validator = validators.Validator().require_presence_of('scheme', 'path')
|
|
with pytest.raises(exceptions.MissingComponentError) as captured_exc:
|
|
validator.validate(uri)
|
|
exception = captured_exc.value
|
|
assert 2 == len(exception.args[-1])
|
|
|
|
|
|
@pytest.mark.parametrize('uri', [
|
|
rfc3986.uri_reference('smtp://'),
|
|
rfc3986.uri_reference('telnet://'),
|
|
])
|
|
def test_ensure_uri_has_a_scheme(uri):
|
|
"""Verify validation with allowed schemes."""
|
|
validator = validators.Validator().allow_schemes('https', 'http')
|
|
with pytest.raises(exceptions.UnpermittedComponentError):
|
|
validator.validate(uri)
|
|
|
|
|
|
@pytest.mark.parametrize('uri, failed_component', [
|
|
(rfc3986.uri_reference('git://github.com'), 'scheme'),
|
|
(rfc3986.uri_reference('http://github.com'), 'scheme'),
|
|
(rfc3986.uri_reference('ssh://gitlab.com'), 'host'),
|
|
(rfc3986.uri_reference('https://gitlab.com'), 'host'),
|
|
])
|
|
def test_allowed_hosts_and_schemes(uri, failed_component):
|
|
"""Verify each of these fails."""
|
|
validator = validators.Validator().allow_schemes(
|
|
'https', 'ssh',
|
|
).allow_hosts(
|
|
'github.com', 'git.openstack.org',
|
|
)
|
|
with pytest.raises(exceptions.UnpermittedComponentError) as caught_exc:
|
|
validator.validate(uri)
|
|
|
|
exc = caught_exc.value
|
|
assert exc.component_name == failed_component
|
|
|
|
|
|
@pytest.mark.parametrize('uri', [
|
|
rfc3986.uri_reference('https://github.com/sigmavirus24'),
|
|
rfc3986.uri_reference('ssh://github.com/sigmavirus24'),
|
|
rfc3986.uri_reference('ssh://ssh@github.com:22/sigmavirus24'),
|
|
rfc3986.uri_reference('https://github.com:443/sigmavirus24'),
|
|
rfc3986.uri_reference('https://gitlab.com/sigmavirus24'),
|
|
rfc3986.uri_reference('ssh://gitlab.com/sigmavirus24'),
|
|
rfc3986.uri_reference('ssh://ssh@gitlab.com:22/sigmavirus24'),
|
|
rfc3986.uri_reference('https://gitlab.com:443/sigmavirus24'),
|
|
rfc3986.uri_reference('https://bitbucket.org/sigmavirus24'),
|
|
rfc3986.uri_reference('ssh://bitbucket.org/sigmavirus24'),
|
|
rfc3986.uri_reference('ssh://ssh@bitbucket.org:22/sigmavirus24'),
|
|
rfc3986.uri_reference('https://bitbucket.org:443/sigmavirus24'),
|
|
rfc3986.uri_reference('https://git.openstack.org/sigmavirus24'),
|
|
rfc3986.uri_reference('ssh://git.openstack.org/sigmavirus24'),
|
|
rfc3986.uri_reference('ssh://ssh@git.openstack.org:22/sigmavirus24'),
|
|
rfc3986.uri_reference('https://git.openstack.org:443/sigmavirus24'),
|
|
])
|
|
def test_successful_complex_validation(uri):
|
|
"""Verify we do not raise ValidationErrors for good URIs."""
|
|
validators.Validator().allow_schemes(
|
|
'https', 'ssh',
|
|
).allow_hosts(
|
|
'github.com', 'bitbucket.org', 'gitlab.com', 'git.openstack.org',
|
|
).allow_ports(
|
|
'22', '443',
|
|
).require_presence_of(
|
|
'scheme', 'host', 'path',
|
|
).validate(uri)
|