Skip to content

Commit 203b944

Browse files
committed
tests: Add tests for ProxyEnvironment
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]>
1 parent 4989447 commit 203b944

File tree

1 file changed

+186
-0
lines changed

1 file changed

+186
-0
lines changed

tests/test_proxy_environment.py

+186
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
# Copyright 2025, the TUF contributors
2+
# SPDX-License-Identifier: MIT OR Apache-2.0
3+
4+
"""Test ngclient ProxyEnvironment"""
5+
6+
import sys
7+
import unittest
8+
from unittest.mock import Mock, patch
9+
10+
from urllib3 import PoolManager, ProxyManager
11+
12+
from tests import utils
13+
from tuf.ngclient._internal.proxy import ProxyEnvironment
14+
15+
16+
class TestProxyEnvironment(unittest.TestCase):
17+
"""Test ngclient ProxyEnvironment implementation
18+
19+
These tests use the ProxyEnvironment.get_pool_manager() endpoint and then
20+
look at the ProxyEnvironment._poolmanagers dict keys to decide if the result
21+
is correct.
22+
23+
The test environment is changed via mocking getproxies(): this is a urllib
24+
method that returns a dict with the proxy environment variable contents.
25+
26+
Testing ProxyEnvironment.request() would possibly be better but far more
27+
difficult: the current test implementation does not require actually setting up
28+
all of the different proxies.
29+
"""
30+
31+
def assert_pool_managers(
32+
self, env: ProxyEnvironment, expected: list[str | None]
33+
) -> None:
34+
# Pool managers have the expected proxy urls
35+
self.assertEqual(list(env._pool_managers.keys()), expected)
36+
37+
# Pool manager types are as expected
38+
for proxy_url, pool_manager in env._pool_managers.items():
39+
self.assertIsInstance(pool_manager, PoolManager)
40+
if proxy_url is not None:
41+
self.assertIsInstance(pool_manager, ProxyManager)
42+
43+
@patch("tuf.ngclient._internal.proxy.getproxies")
44+
def test_no_variables(self, mock_getproxies: Mock) -> None:
45+
mock_getproxies.return_value = {}
46+
47+
env = ProxyEnvironment()
48+
env.get_pool_manager("http", "example.com")
49+
env.get_pool_manager("https", "example.com")
50+
env.get_pool_manager("https", "example.com")
51+
env.get_pool_manager("https", "subdomain.example.com")
52+
env.get_pool_manager("https", "differentsite.com")
53+
54+
# There is a single pool manager (no proxies)
55+
self.assert_pool_managers(env, [None])
56+
57+
@patch("tuf.ngclient._internal.proxy.getproxies")
58+
def test_proxy_set(self, mock_getproxies: Mock) -> None:
59+
mock_getproxies.return_value = {
60+
"https": "http://localhost:8888",
61+
}
62+
63+
env = ProxyEnvironment()
64+
env.get_pool_manager("http", "example.com")
65+
env.get_pool_manager("https", "example.com")
66+
env.get_pool_manager("https", "example.com")
67+
env.get_pool_manager("https", "differentsite.com")
68+
69+
# There are two pool managers: A plain poolmanager and https proxymanager
70+
self.assert_pool_managers(env, [None, "http://localhost:8888"])
71+
72+
@patch("tuf.ngclient._internal.proxy.getproxies")
73+
def test_proxies_set(self, mock_getproxies: Mock) -> None:
74+
mock_getproxies.return_value = {
75+
"http": "http://localhost:8888",
76+
"https": "http://localhost:9999",
77+
}
78+
79+
env = ProxyEnvironment()
80+
env.get_pool_manager("http", "example.com")
81+
env.get_pool_manager("https", "example.com")
82+
env.get_pool_manager("https", "example.com")
83+
env.get_pool_manager("https", "subdomain.example.com")
84+
env.get_pool_manager("https", "differentsite.com")
85+
86+
# There are two pool managers: A http proxymanager and https proxymanager
87+
self.assert_pool_managers(
88+
env, ["http://localhost:8888", "http://localhost:9999"]
89+
)
90+
91+
@patch("tuf.ngclient._internal.proxy.getproxies")
92+
def test_no_proxy_set(self, mock_getproxies: Mock) -> None:
93+
mock_getproxies.return_value = {
94+
"http": "http://localhost:8888",
95+
"https": "http://localhost:9999",
96+
"no": "somesite.com, example.com, another.site.com",
97+
}
98+
99+
env = ProxyEnvironment()
100+
env.get_pool_manager("http", "example.com")
101+
env.get_pool_manager("https", "example.com")
102+
env.get_pool_manager("https", "example.com")
103+
104+
# There is a single pool manager (no proxies)
105+
self.assert_pool_managers(env, [None])
106+
107+
env.get_pool_manager("http", "differentsite.com")
108+
env.get_pool_manager("https", "differentsite.com")
109+
110+
# There are three pool managers: plain poolmanager for no_proxy domains,
111+
# http proxymanager and https proxymanager
112+
self.assert_pool_managers(
113+
env, [None, "http://localhost:8888", "http://localhost:9999"]
114+
)
115+
116+
@patch("tuf.ngclient._internal.proxy.getproxies")
117+
def test_no_proxy_subdomain_match(self, mock_getproxies: Mock) -> None:
118+
mock_getproxies.return_value = {
119+
"https": "http://localhost:9999",
120+
"no": "somesite.com, example.com, another.site.com",
121+
}
122+
123+
env = ProxyEnvironment()
124+
125+
# this should match example.com in no_proxy
126+
env.get_pool_manager("https", "subdomain.example.com")
127+
128+
# There is a single pool manager (no proxies)
129+
self.assert_pool_managers(env, [None])
130+
131+
# this should not match example.com in no_proxy
132+
env.get_pool_manager("https", "xexample.com")
133+
134+
# There are two pool managers: plain poolmanager for no_proxy domains,
135+
# and a https proxymanager
136+
self.assert_pool_managers(env, [None, "http://localhost:9999"])
137+
138+
@patch("tuf.ngclient._internal.proxy.getproxies")
139+
def test_all_proxy_set(self, mock_getproxies: Mock) -> None:
140+
mock_getproxies.return_value = {
141+
"all": "http://localhost:8888",
142+
}
143+
144+
env = ProxyEnvironment()
145+
env.get_pool_manager("http", "example.com")
146+
env.get_pool_manager("https", "example.com")
147+
env.get_pool_manager("https", "example.com")
148+
env.get_pool_manager("https", "subdomain.example.com")
149+
env.get_pool_manager("https", "differentsite.com")
150+
151+
# There is a single proxy manager
152+
self.assert_pool_managers(env, ["http://localhost:8888"])
153+
154+
# This urllib3 currently only handles http and https but let's test anyway
155+
env.get_pool_manager("file", None)
156+
157+
# proxy manager and a plain pool manager
158+
self.assert_pool_managers(env, ["http://localhost:8888", None])
159+
160+
@patch("tuf.ngclient._internal.proxy.getproxies")
161+
def test_all_proxy_and_no_proxy_set(self, mock_getproxies: Mock) -> None:
162+
mock_getproxies.return_value = {
163+
"all": "http://localhost:8888",
164+
"no": "somesite.com, example.com, another.site.com",
165+
}
166+
167+
env = ProxyEnvironment()
168+
env.get_pool_manager("http", "example.com")
169+
env.get_pool_manager("https", "example.com")
170+
env.get_pool_manager("https", "example.com")
171+
env.get_pool_manager("https", "subdomain.example.com")
172+
173+
# There is a single pool manager (no proxies)
174+
self.assert_pool_managers(env, [None])
175+
176+
env.get_pool_manager("http", "differentsite.com")
177+
env.get_pool_manager("https", "differentsite.com")
178+
179+
# There are two pool managers: plain poolmanager for no_proxy domains and
180+
# one proxymanager
181+
self.assert_pool_managers(env, [None, "http://localhost:8888"])
182+
183+
184+
if __name__ == "__main__":
185+
utils.configure_test_logging(sys.argv)
186+
unittest.main()

0 commit comments

Comments
 (0)