Skip to content

Commit ed4bd50

Browse files
committed
Revert "removed unnecessary test"
This reverts commit ad663e5.
1 parent ad663e5 commit ed4bd50

File tree

1 file changed

+74
-1
lines changed

1 file changed

+74
-1
lines changed

tests/test_litellm/proxy/guardrails/guardrail_hooks/test_bedrock_guardrails.py

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1048,4 +1048,77 @@ async def test_bedrock_guardrail_parameter_takes_precedence_over_env(monkeypatch
10481048
prepped_request.url == expected_url
10491049
), f"Expected parameter endpoint to take precedence. Got: {prepped_request.url}"
10501050

1051-
print(f"Parameter precedence test passed. URL: {prepped_request.url}")
1051+
print(f"Parameter precedence test passed. URL: {prepped_request.url}")
1052+
1053+
@pytest.mark.asyncio
1054+
async def test_bedrock_guardrail_200_with_exception_in_output_raises_and_logs_failure():
1055+
"""
1056+
When Bedrock returns HTTP 200 but the body contains Output.__type with 'Exception',
1057+
the guardrail should:
1058+
- raise an HTTPException(400) with the Output payload in detail
1059+
- log the request trace with guardrail_status='failure'
1060+
"""
1061+
guardrail = BedrockGuardrail(
1062+
guardrailIdentifier="test-guardrail", guardrailVersion="DRAFT"
1063+
)
1064+
1065+
# Mock a Bedrock "success" HTTP status but an Exception embedded in the body
1066+
payload = {
1067+
"Output": {
1068+
"__type": "com.amazonaws#InternalServerException",
1069+
"message": "Something went wrong upstream",
1070+
},
1071+
"action": "NONE",
1072+
}
1073+
mock_resp = MagicMock()
1074+
mock_resp.status_code = 200
1075+
mock_resp.content = json.dumps(payload).encode("utf-8")
1076+
mock_resp.text = json.dumps(payload)
1077+
mock_resp.json.return_value = payload
1078+
1079+
# Minimal request data
1080+
request_data = {
1081+
"model": "gpt-4o",
1082+
"messages": [{"role": "user", "content": "hello"}],
1083+
}
1084+
1085+
# Mock creds and request prep
1086+
mock_credentials = MagicMock()
1087+
mock_credentials.access_key = "ak"
1088+
mock_credentials.secret_key = "sk"
1089+
mock_credentials.token = None
1090+
1091+
with patch.object(
1092+
guardrail.async_handler, "post", new_callable=AsyncMock
1093+
) as mock_post, patch.object(
1094+
guardrail, "_load_credentials", return_value=(mock_credentials, "us-east-1")
1095+
), patch.object(
1096+
guardrail,
1097+
"_prepare_request",
1098+
return_value=MagicMock(url="http://example", headers={}, body=b""),
1099+
), patch.object(
1100+
guardrail, "add_standard_logging_guardrail_information_to_request_data"
1101+
) as mock_add_trace:
1102+
mock_post.return_value = mock_resp
1103+
1104+
with pytest.raises(HTTPException) as excinfo:
1105+
await guardrail.make_bedrock_api_request(
1106+
source="INPUT",
1107+
messages=request_data["messages"],
1108+
request_data=request_data,
1109+
)
1110+
1111+
# 1) Raised HTTPException with 400 status
1112+
err = excinfo.value
1113+
assert err.status_code == 400
1114+
assert err.detail["error"] == "Guardrail application failed."
1115+
1116+
# 2) Detail includes the Output object from the Bedrock body
1117+
assert err.detail["bedrock_guardrail_response"] == payload["Output"]
1118+
1119+
# 3) Trace logging received a 'failure' status
1120+
assert mock_add_trace.called
1121+
_, kwargs = mock_add_trace.call_args
1122+
assert kwargs["guardrail_status"] == "failure"
1123+
# And the JSON passed to tracing is the same response we received
1124+
assert kwargs["guardrail_json_response"] == payload

0 commit comments

Comments
 (0)