Skip to content

Commit

Permalink
tests: Add tests for ProxyEnvironment
Browse files Browse the repository at this point in the history
This does not actually test using tuf through proxies: it only tests
that ProxyEnvironment creates the ProxyManagers that we expect to be
created based on the proxy environment variables.

Signed-off-by: Jussi Kukkonen <[email protected]>
  • Loading branch information
jku committed Feb 14, 2025
1 parent 4989447 commit 203b944
Showing 1 changed file with 186 additions and 0 deletions.
186 changes: 186 additions & 0 deletions tests/test_proxy_environment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
# Copyright 2025, the TUF contributors
# SPDX-License-Identifier: MIT OR Apache-2.0

"""Test ngclient ProxyEnvironment"""

import sys
import unittest
from unittest.mock import Mock, patch

from urllib3 import PoolManager, ProxyManager

from tests import utils
from tuf.ngclient._internal.proxy import ProxyEnvironment


class TestProxyEnvironment(unittest.TestCase):
"""Test ngclient ProxyEnvironment implementation
These tests use the ProxyEnvironment.get_pool_manager() endpoint and then
look at the ProxyEnvironment._poolmanagers dict keys to decide if the result
is correct.
The test environment is changed via mocking getproxies(): this is a urllib
method that returns a dict with the proxy environment variable contents.
Testing ProxyEnvironment.request() would possibly be better but far more
difficult: the current test implementation does not require actually setting up
all of the different proxies.
"""

def assert_pool_managers(
self, env: ProxyEnvironment, expected: list[str | None]
) -> None:
# Pool managers have the expected proxy urls
self.assertEqual(list(env._pool_managers.keys()), expected)

# Pool manager types are as expected
for proxy_url, pool_manager in env._pool_managers.items():
self.assertIsInstance(pool_manager, PoolManager)
if proxy_url is not None:
self.assertIsInstance(pool_manager, ProxyManager)

@patch("tuf.ngclient._internal.proxy.getproxies")
def test_no_variables(self, mock_getproxies: Mock) -> None:
mock_getproxies.return_value = {}

env = ProxyEnvironment()
env.get_pool_manager("http", "example.com")
env.get_pool_manager("https", "example.com")
env.get_pool_manager("https", "example.com")
env.get_pool_manager("https", "subdomain.example.com")
env.get_pool_manager("https", "differentsite.com")

# There is a single pool manager (no proxies)
self.assert_pool_managers(env, [None])

@patch("tuf.ngclient._internal.proxy.getproxies")
def test_proxy_set(self, mock_getproxies: Mock) -> None:
mock_getproxies.return_value = {
"https": "http://localhost:8888",
}

env = ProxyEnvironment()
env.get_pool_manager("http", "example.com")
env.get_pool_manager("https", "example.com")
env.get_pool_manager("https", "example.com")
env.get_pool_manager("https", "differentsite.com")

# There are two pool managers: A plain poolmanager and https proxymanager
self.assert_pool_managers(env, [None, "http://localhost:8888"])

@patch("tuf.ngclient._internal.proxy.getproxies")
def test_proxies_set(self, mock_getproxies: Mock) -> None:
mock_getproxies.return_value = {
"http": "http://localhost:8888",
"https": "http://localhost:9999",
}

env = ProxyEnvironment()
env.get_pool_manager("http", "example.com")
env.get_pool_manager("https", "example.com")
env.get_pool_manager("https", "example.com")
env.get_pool_manager("https", "subdomain.example.com")
env.get_pool_manager("https", "differentsite.com")

# There are two pool managers: A http proxymanager and https proxymanager
self.assert_pool_managers(
env, ["http://localhost:8888", "http://localhost:9999"]
)

@patch("tuf.ngclient._internal.proxy.getproxies")
def test_no_proxy_set(self, mock_getproxies: Mock) -> None:
mock_getproxies.return_value = {
"http": "http://localhost:8888",
"https": "http://localhost:9999",
"no": "somesite.com, example.com, another.site.com",
}

env = ProxyEnvironment()
env.get_pool_manager("http", "example.com")
env.get_pool_manager("https", "example.com")
env.get_pool_manager("https", "example.com")

# There is a single pool manager (no proxies)
self.assert_pool_managers(env, [None])

env.get_pool_manager("http", "differentsite.com")
env.get_pool_manager("https", "differentsite.com")

# There are three pool managers: plain poolmanager for no_proxy domains,
# http proxymanager and https proxymanager
self.assert_pool_managers(
env, [None, "http://localhost:8888", "http://localhost:9999"]
)

@patch("tuf.ngclient._internal.proxy.getproxies")
def test_no_proxy_subdomain_match(self, mock_getproxies: Mock) -> None:
mock_getproxies.return_value = {
"https": "http://localhost:9999",
"no": "somesite.com, example.com, another.site.com",
}

env = ProxyEnvironment()

# this should match example.com in no_proxy
env.get_pool_manager("https", "subdomain.example.com")

# There is a single pool manager (no proxies)
self.assert_pool_managers(env, [None])

# this should not match example.com in no_proxy
env.get_pool_manager("https", "xexample.com")

# There are two pool managers: plain poolmanager for no_proxy domains,
# and a https proxymanager
self.assert_pool_managers(env, [None, "http://localhost:9999"])

@patch("tuf.ngclient._internal.proxy.getproxies")
def test_all_proxy_set(self, mock_getproxies: Mock) -> None:
mock_getproxies.return_value = {
"all": "http://localhost:8888",
}

env = ProxyEnvironment()
env.get_pool_manager("http", "example.com")
env.get_pool_manager("https", "example.com")
env.get_pool_manager("https", "example.com")
env.get_pool_manager("https", "subdomain.example.com")
env.get_pool_manager("https", "differentsite.com")

# There is a single proxy manager
self.assert_pool_managers(env, ["http://localhost:8888"])

# This urllib3 currently only handles http and https but let's test anyway
env.get_pool_manager("file", None)

# proxy manager and a plain pool manager
self.assert_pool_managers(env, ["http://localhost:8888", None])

@patch("tuf.ngclient._internal.proxy.getproxies")
def test_all_proxy_and_no_proxy_set(self, mock_getproxies: Mock) -> None:
mock_getproxies.return_value = {
"all": "http://localhost:8888",
"no": "somesite.com, example.com, another.site.com",
}

env = ProxyEnvironment()
env.get_pool_manager("http", "example.com")
env.get_pool_manager("https", "example.com")
env.get_pool_manager("https", "example.com")
env.get_pool_manager("https", "subdomain.example.com")

# There is a single pool manager (no proxies)
self.assert_pool_managers(env, [None])

env.get_pool_manager("http", "differentsite.com")
env.get_pool_manager("https", "differentsite.com")

# There are two pool managers: plain poolmanager for no_proxy domains and
# one proxymanager
self.assert_pool_managers(env, [None, "http://localhost:8888"])


if __name__ == "__main__":
utils.configure_test_logging(sys.argv)
unittest.main()

0 comments on commit 203b944

Please sign in to comment.