1
1
Fork 0
mirror of https://github.com/pypa/pip synced 2023-12-13 21:30:23 +01:00
pip/tests/unit/test_networking_auth.py
Chris Hunt db766f3c95 Move helper mock classes to dedicated module
When we factor out tests these will be needed in both sets, and it's
easier to refactor tests later if we avoid creating a dependency between
test files.
2019-12-04 18:30:21 -05:00

225 lines
7.2 KiB
Python

import functools
import pytest
import pip._internal.network.auth
from pip._internal.network.auth import MultiDomainBasicAuth
from tests.lib.requests_mocks import MockConnection, MockRequest, MockResponse
@pytest.mark.parametrize(["input_url", "url", "username", "password"], [
(
"http://user%40email.com:password@example.com/path",
"http://example.com/path",
"user@email.com",
"password",
),
(
"http://username:password@example.com/path",
"http://example.com/path",
"username",
"password",
),
(
"http://token@example.com/path",
"http://example.com/path",
"token",
"",
),
(
"http://example.com/path",
"http://example.com/path",
None,
None,
),
])
def test_get_credentials_parses_correctly(input_url, url, username, password):
auth = MultiDomainBasicAuth()
get = auth._get_url_and_credentials
# Check URL parsing
assert get(input_url) == (url, username, password)
assert (
# There are no credentials in the URL
(username is None and password is None) or
# Credentials were found and "cached" appropriately
auth.passwords['example.com'] == (username, password)
)
def test_get_credentials_uses_cached_credentials():
auth = MultiDomainBasicAuth()
auth.passwords['example.com'] = ('user', 'pass')
got = auth._get_url_and_credentials("http://foo:bar@example.com/path")
expected = ('http://example.com/path', 'user', 'pass')
assert got == expected
def test_get_index_url_credentials():
auth = MultiDomainBasicAuth(index_urls=[
"http://foo:bar@example.com/path"
])
get = functools.partial(
auth._get_new_credentials,
allow_netrc=False,
allow_keyring=False
)
# Check resolution of indexes
assert get("http://example.com/path/path2") == ('foo', 'bar')
assert get("http://example.com/path3/path2") == (None, None)
class KeyringModuleV1(object):
"""Represents the supported API of keyring before get_credential
was added.
"""
def __init__(self):
self.saved_passwords = []
def get_password(self, system, username):
if system == "example.com" and username:
return username + "!netloc"
if system == "http://example.com/path2" and username:
return username + "!url"
return None
def set_password(self, system, username, password):
self.saved_passwords.append((system, username, password))
@pytest.mark.parametrize('url, expect', (
("http://example.com/path1", (None, None)),
# path1 URLs will be resolved by netloc
("http://user@example.com/path1", ("user", "user!netloc")),
("http://user2@example.com/path1", ("user2", "user2!netloc")),
# path2 URLs will be resolved by index URL
("http://example.com/path2/path3", (None, None)),
("http://foo@example.com/path2/path3", ("foo", "foo!url")),
))
def test_keyring_get_password(monkeypatch, url, expect):
keyring = KeyringModuleV1()
monkeypatch.setattr('pip._internal.network.auth.keyring', keyring)
auth = MultiDomainBasicAuth(index_urls=["http://example.com/path2"])
actual = auth._get_new_credentials(url, allow_netrc=False,
allow_keyring=True)
assert actual == expect
def test_keyring_get_password_after_prompt(monkeypatch):
keyring = KeyringModuleV1()
monkeypatch.setattr('pip._internal.network.auth.keyring', keyring)
auth = MultiDomainBasicAuth()
def ask_input(prompt):
assert prompt == "User for example.com: "
return "user"
monkeypatch.setattr('pip._internal.network.auth.ask_input', ask_input)
actual = auth._prompt_for_password("example.com")
assert actual == ("user", "user!netloc", False)
def test_keyring_get_password_username_in_index(monkeypatch):
keyring = KeyringModuleV1()
monkeypatch.setattr('pip._internal.network.auth.keyring', keyring)
auth = MultiDomainBasicAuth(index_urls=["http://user@example.com/path2"])
get = functools.partial(
auth._get_new_credentials,
allow_netrc=False,
allow_keyring=True
)
assert get("http://example.com/path2/path3") == ("user", "user!url")
assert get("http://example.com/path4/path1") == (None, None)
@pytest.mark.parametrize("response_status, creds, expect_save", (
(403, ("user", "pass", True), False),
(200, ("user", "pass", True), True,),
(200, ("user", "pass", False), False,),
))
def test_keyring_set_password(monkeypatch, response_status, creds,
expect_save):
keyring = KeyringModuleV1()
monkeypatch.setattr('pip._internal.network.auth.keyring', keyring)
auth = MultiDomainBasicAuth(prompting=True)
monkeypatch.setattr(auth, '_get_url_and_credentials',
lambda u: (u, None, None))
monkeypatch.setattr(auth, '_prompt_for_password', lambda *a: creds)
if creds[2]:
# when _prompt_for_password indicates to save, we should save
def should_save_password_to_keyring(*a):
return True
else:
# when _prompt_for_password indicates not to save, we should
# never call this function
def should_save_password_to_keyring(*a):
assert False, ("_should_save_password_to_keyring should not be " +
"called")
monkeypatch.setattr(auth, '_should_save_password_to_keyring',
should_save_password_to_keyring)
req = MockRequest("https://example.com")
resp = MockResponse(b"")
resp.url = req.url
connection = MockConnection()
def _send(sent_req, **kwargs):
assert sent_req is req
assert "Authorization" in sent_req.headers
r = MockResponse(b"")
r.status_code = response_status
return r
connection._send = _send
resp.request = req
resp.status_code = 401
resp.connection = connection
auth.handle_401(resp)
if expect_save:
assert keyring.saved_passwords == [("example.com", creds[0], creds[1])]
else:
assert keyring.saved_passwords == []
class KeyringModuleV2(object):
"""Represents the current supported API of keyring"""
class Credential(object):
def __init__(self, username, password):
self.username = username
self.password = password
def get_password(self, system, username):
assert False, "get_password should not ever be called"
def get_credential(self, system, username):
if system == "http://example.com/path2":
return self.Credential("username", "url")
if system == "example.com":
return self.Credential("username", "netloc")
return None
@pytest.mark.parametrize('url, expect', (
("http://example.com/path1", ("username", "netloc")),
("http://example.com/path2/path3", ("username", "url")),
("http://user2@example.com/path2/path3", ("username", "url")),
))
def test_keyring_get_credential(monkeypatch, url, expect):
monkeypatch.setattr(
pip._internal.network.auth, 'keyring', KeyringModuleV2()
)
auth = MultiDomainBasicAuth(index_urls=["http://example.com/path2"])
assert auth._get_new_credentials(
url, allow_netrc=False, allow_keyring=True
) == expect