mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-30 06:43:27 +00:00
test(inference): pin provider URL redaction on every route's transport error
Chat, Messages, Responses and transcription each get a route-level test that fails if a reqwest error reaches the caller with its URL. The Messages stream decoder also takes body errors through litellm_http::Error like every other reqwest error Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
ca8c6c698f
commit
326e5cc4a8
6 changed files with 71 additions and 1 deletions
|
|
@ -221,6 +221,23 @@ async fn a_connection_that_is_never_established_returns_a_connect_error(
|
|||
);
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
#[tokio::test]
|
||||
async fn a_transport_error_does_not_echo_the_provider_url(
|
||||
request: ChatCompletionsRequest<'static>,
|
||||
) {
|
||||
let base = format!("{UNREACHABLE_BASE}/tenant-token-1234");
|
||||
|
||||
let error = complete(ChatCompletionsRequest {
|
||||
api_base: Some(&base),
|
||||
..request
|
||||
})
|
||||
.await
|
||||
.expect_err("nothing is listening");
|
||||
|
||||
assert!(!error.to_string().contains("tenant-token-1234"), "{error}");
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
#[tokio::test]
|
||||
async fn a_timeout_after_sending_returns_a_network_error(request: ChatCompletionsRequest<'static>) {
|
||||
|
|
|
|||
|
|
@ -359,7 +359,7 @@ fn decoded_chunks(
|
|||
let bytes: ByteStream = response
|
||||
.bytes_stream()
|
||||
.inspect_ok(move |chunk| log_chunk(provider, "provider_response", chunk))
|
||||
.map_err(std::io::Error::other)
|
||||
.map_err(|error| std::io::Error::other(litellm_http::Error::from(error)))
|
||||
.boxed();
|
||||
futures_util::stream::try_unfold(decode(bytes), move |mut events| async move {
|
||||
let Some(event) = events.try_next().await? else {
|
||||
|
|
|
|||
|
|
@ -255,6 +255,20 @@ async fn a_provider_slower_than_the_timeout_fails_the_call(call: MessagesCall) {
|
|||
assert!(matches!(error, Error::Http(_)), "{error:?}");
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
#[tokio::test]
|
||||
async fn a_transport_error_does_not_echo_the_provider_url(call: MessagesCall) {
|
||||
let error = run(MessagesCall {
|
||||
api_key: Some("sk".into()),
|
||||
api_base: Some(format!("{UNREACHABLE_BASE}/tenant-token-1234")),
|
||||
..call
|
||||
})
|
||||
.await
|
||||
.expect_err("nothing is listening");
|
||||
|
||||
assert!(!error.to_string().contains("tenant-token-1234"), "{error}");
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
#[tokio::test]
|
||||
async fn the_facade_sends_through_the_injected_http_pool_configuration(call: MessagesCall) {
|
||||
|
|
|
|||
|
|
@ -304,6 +304,25 @@ async fn provider_failures_emit_failure_once(
|
|||
);
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
#[tokio::test]
|
||||
async fn a_transport_error_does_not_echo_the_provider_url(call: ResponsesCall) {
|
||||
let host = RecordingCall::<Responses>::new(ResponsesCall {
|
||||
api_base: Some(format!("{UNREACHABLE_BASE}/tenant-token-1234")),
|
||||
..call
|
||||
});
|
||||
let call = host.request.lock().unwrap().take().unwrap();
|
||||
|
||||
let Err(error) = responses_route(no_secrets())
|
||||
.execute(call, &host, None)
|
||||
.await
|
||||
else {
|
||||
panic!("nothing is listening");
|
||||
};
|
||||
|
||||
assert!(!error.to_string().contains("tenant-token-1234"), "{error}");
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
#[case::explicit(true)]
|
||||
#[case::from_secrets(false)]
|
||||
|
|
|
|||
|
|
@ -13,6 +13,9 @@ use litellm_secrets::source::SecretSource;
|
|||
use serde_json::Value;
|
||||
use wiremock::{Mock, MockServer, Request, ResponseTemplate, matchers::any};
|
||||
|
||||
/// A port nothing listens on, for calls that must fail before any request is sent.
|
||||
pub const UNREACHABLE_BASE: &str = "http://127.0.0.1:1";
|
||||
|
||||
pub fn responses_route(
|
||||
secrets: Arc<dyn SecretSource>,
|
||||
) -> litellm_inference_responses::ResponsesRoute {
|
||||
|
|
|
|||
|
|
@ -227,6 +227,23 @@ async fn an_upstream_error_keeps_its_status_and_body(
|
|||
);
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
#[tokio::test]
|
||||
async fn a_transport_error_does_not_echo_the_provider_url(
|
||||
request: AudioTranscriptionRequest<'static>,
|
||||
) {
|
||||
let base = format!("{UNREACHABLE_BASE}/tenant-token-1234");
|
||||
|
||||
let error = transcribe(AudioTranscriptionRequest {
|
||||
api_base: Some(&base),
|
||||
..request
|
||||
})
|
||||
.await
|
||||
.expect_err("nothing is listening");
|
||||
|
||||
assert!(!error.to_string().contains("tenant-token-1234"), "{error}");
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
#[case::not_json(ResponseTemplate::new(200).set_body_string("not json"))]
|
||||
#[case::no_output(json_response(json!({"unexpected": true})))]
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue