Skip to content

Commit 07fc1cd

Browse files
committed
Improved code coverage for new functionalities added before
Signed-off-by: Jitesh Nair <jiteshnair@ibm.com>
1 parent 52ade43 commit 07fc1cd

File tree

1 file changed

+122
-0
lines changed

1 file changed

+122
-0
lines changed

tests/unit/mcpgateway/test_main_helpers.py

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,128 @@ async def test_invalidate_resource_cache_clears_entries():
184184
assert main.resource_cache.get("/resource2") is None
185185

186186

187+
def test_validate_http_headers_valid():
188+
"""Test _validate_http_headers with valid headers."""
189+
headers = {
190+
"Content-Type": "application/json",
191+
"Authorization": "Bearer token123",
192+
"X-Custom-Header": "value with spaces",
193+
}
194+
result = main._validate_http_headers(headers)
195+
assert result == headers
196+
197+
198+
def test_validate_http_headers_invalid_name():
199+
"""Test _validate_http_headers rejects invalid header names (line 1435-1436)."""
200+
# Invalid header name with space
201+
headers = {"Invalid Name": "value"}
202+
result = main._validate_http_headers(headers)
203+
assert result is None
204+
205+
# Invalid header name with special characters not in RFC 9110 token
206+
headers = {"Invalid@Header": "value"}
207+
result = main._validate_http_headers(headers)
208+
assert result is None
209+
210+
# Mix of valid and invalid headers
211+
headers = {
212+
"Valid-Header": "value1",
213+
"Invalid Name": "value2",
214+
"Another-Valid": "value3",
215+
}
216+
result = main._validate_http_headers(headers)
217+
assert result == {"Valid-Header": "value1", "Another-Valid": "value3"}
218+
219+
220+
def test_validate_http_headers_crlf_in_value():
221+
"""Test _validate_http_headers rejects CRLF in header values (line 1439-1440)."""
222+
# Header value with carriage return
223+
headers = {"Content-Type": "application/json\rinjection"}
224+
result = main._validate_http_headers(headers)
225+
assert result is None
226+
227+
# Header value with newline
228+
headers = {"Authorization": "Bearer token\ninjection"}
229+
result = main._validate_http_headers(headers)
230+
assert result is None
231+
232+
# Header value with both CRLF
233+
headers = {"X-Custom": "value\r\ninjection"}
234+
result = main._validate_http_headers(headers)
235+
assert result is None
236+
237+
# Mix of valid and invalid headers
238+
headers = {
239+
"Valid-Header": "clean value",
240+
"Invalid-Header": "value\r\ninjection",
241+
"Another-Valid": "another clean value",
242+
}
243+
result = main._validate_http_headers(headers)
244+
assert result == {"Valid-Header": "clean value", "Another-Valid": "another clean value"}
245+
246+
247+
def test_validate_http_headers_ctl_characters():
248+
"""Test _validate_http_headers rejects CTL characters in values (line 1447-1448, 1450)."""
249+
# Header value with null byte (0x00)
250+
headers = {"Content-Type": "application/json\x00"}
251+
result = main._validate_http_headers(headers)
252+
assert result is None
253+
254+
# Header value with control character (0x01)
255+
headers = {"Authorization": "Bearer\x01token"}
256+
result = main._validate_http_headers(headers)
257+
assert result is None
258+
259+
# Header value with DEL character (0x7F)
260+
headers = {"X-Custom": "value\x7f"}
261+
result = main._validate_http_headers(headers)
262+
assert result is None
263+
264+
# Header value with various CTL characters (0x00-0x1F except tab and space)
265+
for code in range(0, 32):
266+
if code in (9, 32): # Skip tab and space (allowed)
267+
continue
268+
headers = {"Test-Header": f"value{chr(code)}end"}
269+
result = main._validate_http_headers(headers)
270+
assert result is None, f"Should reject CTL character 0x{code:02x}"
271+
272+
# Header value with tab (0x09) - should be allowed
273+
headers = {"Content-Type": "application/json\tcharset=utf-8"}
274+
result = main._validate_http_headers(headers)
275+
assert result == headers
276+
277+
# Header value with space (0x20) - should be allowed
278+
headers = {"Authorization": "Bearer token with spaces"}
279+
result = main._validate_http_headers(headers)
280+
assert result == headers
281+
282+
# Mix of valid and invalid headers
283+
headers = {
284+
"Valid-Header": "clean value",
285+
"Invalid-Header": "value\x01injection",
286+
"Another-Valid": "another clean value",
287+
}
288+
result = main._validate_http_headers(headers)
289+
assert result == {"Valid-Header": "clean value", "Another-Valid": "another clean value"}
290+
291+
292+
def test_validate_http_headers_empty_dict():
293+
"""Test _validate_http_headers with empty dictionary."""
294+
result = main._validate_http_headers({})
295+
assert result is None
296+
297+
298+
def test_validate_http_headers_all_invalid():
299+
"""Test _validate_http_headers when all headers are invalid."""
300+
headers = {
301+
"Invalid Name": "value1",
302+
"Valid-But-Bad-Value": "value\r\ninjection",
303+
"Another-Invalid": "value\x00",
304+
}
305+
result = main._validate_http_headers(headers)
306+
assert result is None
307+
308+
187309
# ---------------------------------------------------------------------------
188310
# tojson_attr filter tests
189311
# ---------------------------------------------------------------------------

0 commit comments

Comments
 (0)