litellm/litellm-rust/crates/http/tests/request.rs
devin-ai-integration[bot] 268e8bb735
refactor(rust): share anthropic types, request helpers, and streaming contracts across crates (#43426)
* refactor(rust): standardize Azure Messages module path

* docs(rust): define shared types crate boundaries

* refactor(rust): share request helpers and type Anthropic blocks

* docs(rust): format shared type invariants as bullets

* test(rust): parameterize repeated cases with rstest

* refactor(rust): move Responses transform result into llms

* fix(anthropic): validate chat and batch responses

* docs(rust): clarify API format ownership boundaries

* docs: clarify Rust error message construction

* refactor(auth): keep shared Rust errors provider-neutral

* refactor(rust): separate format contracts from provider policy

* fix(rust): type Anthropic chat response text collection

* fix(rust): pass audio secret sources through hosts

* fix(rust): unblock batch lint and OCR error assertions

* test(rust): assert response failures at the adapter boundary

* refactor(rust): declare error messages with typed context

* wip

* fix(rust): adapt Bedrock error details

* style(rust): cargo fmt bedrock audio transcription

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(rust): adapt tests and dead code to typed error details

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(rust): keep converse error contracts and read env secrets without litellm

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* ci(rust): raise the native wheel size gate to 45 MB

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(rust): tolerate missing usage in converse responses on the transcription route

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

---------

Co-authored-by: Yujong Lee <yujong@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-27 14:53:12 -07:00

69 lines
2 KiB
Rust

use litellm_http::request::{header_values, with_default_headers, with_header};
use rstest::{fixture, rstest};
fn headers(pairs: &[(&str, &str)]) -> Vec<(String, String)> {
pairs
.iter()
.map(|(name, value)| (name.to_string(), value.to_string()))
.collect()
}
#[rstest]
#[case::nothing_forwarded(
&[],
&[("x-version", "1"), ("content-type", "application/json")],
&[("x-version", "1"), ("content-type", "application/json")],
)]
#[case::forwarded_header_wins_in_any_case(
&[("X-Version", "custom"), ("x-api-key", "k")],
&[("x-version", "1"), ("content-type", "application/json")],
&[("X-Version", "custom"), ("x-api-key", "k"), ("content-type", "application/json")],
)]
#[case::no_defaults(&[("x-api-key", "k")], &[], &[("x-api-key", "k")])]
fn default_headers_fill_only_missing_names(
#[case] forwarded: &[(&str, &str)],
#[case] defaults: &[(&str, &str)],
#[case] expected: &[(&str, &str)],
) {
assert_eq!(
with_default_headers(headers(forwarded), defaults),
headers(expected)
);
}
#[fixture]
fn forwarded() -> Vec<(String, String)> {
headers(&[
("X-Mode", "first"),
("x-trace", "trace"),
("x-MODE", "second"),
])
}
#[rstest]
#[case::matching_name("X-MODE", vec!["first", "second"])]
#[case::missing_name("missing", vec![])]
fn header_values_preserve_all_matching_values_in_order(
forwarded: Vec<(String, String)>,
#[case] name: &str,
#[case] expected: Vec<&str>,
) {
assert_eq!(
header_values(&forwarded, name).collect::<Vec<_>>(),
expected
);
}
#[rstest]
#[case::replace("X-MODE", &[("x-trace", "trace"), ("x-mode", "new")])]
#[case::insert("X-New", &[("X-Mode", "first"), ("x-trace", "trace"), ("x-MODE", "second"), ("x-new", "new")])]
fn with_header_replaces_every_matching_name_and_preserves_other_headers(
forwarded: Vec<(String, String)>,
#[case] name: &str,
#[case] expected: &[(&str, &str)],
) {
assert_eq!(
with_header(forwarded, name, "new".into()),
headers(expected)
);
}