use super::*;
use crate::catalog::{CatalogOffering, CatalogSource, bundled_offerings_from_models_dev};
use crate::models_dev::{ModelsDevCatalog, ModelsDevCost};
use crate::route::PricingSku;
fn priced(source: CatalogSource) -> CatalogOffering {
CatalogOffering {
provider: "deepseek".into(),
wire_model_id: "deepseek-v4-pro".into(),
canonical_model: Some("deepseek-v4-pro".into()),
endpoint_key: "chat".into(),
cost: Some(ModelsDevCost {
input: Some(0.28),
output: Some(0.42),
cache_read: Some(0.028),
cache_write: None,
}),
source,
..Default::default()
}
}
#[test]
fn maps_models_dev_cost_with_bundled_provenance_in_usd() {
let p =
OfferingPricing::from_catalog_offering(&priced(CatalogSource::Bundled)).expect("priced");
assert_eq!(p.currency, Currency::Usd);
assert_eq!(p.input_per_million, Some(0.28));
assert_eq!(p.output_per_million, Some(0.42));
assert_eq!(p.cache_read_per_million, Some(0.028));
assert_eq!(p.cache_write_per_million, None);
assert_eq!(p.provenance, PricingProvenance::ModelsDevBundled);
assert_eq!(p.effective_at, None);
assert!(p.has_any_price());
}
#[test]
fn malformed_catalog_prices_fail_closed_at_every_projection() {
for invalid in [f64::NAN, f64::INFINITY, f64::NEG_INFINITY, -0.01] {
for field in 0..4 {
let mut offering = priced(CatalogSource::Bundled);
offering.provider = "openrouter".to_string();
offering.wire_model_id = "openai/gpt-5.5".to_string();
let cost = offering.cost.as_mut().expect("cost fixture");
match field {
0 => cost.input = Some(invalid),
1 => cost.output = Some(invalid),
2 => cost.cache_read = Some(invalid),
3 => cost.cache_write = Some(invalid),
_ => unreachable!(),
}
assert!(
OfferingPricing::from_catalog_offering(&offering).is_none(),
"field {field} accepted {invalid:?}"
);
assert_eq!(
route_pricing_sku(&offering),
PricingSku::UnknownOrStale,
"route projection accepted field {field} = {invalid:?}"
);
}
}
let zero = priced(CatalogSource::Bundled);
let mut zero = zero;
let cost = zero.cost.as_mut().expect("cost fixture");
cost.input = Some(0.0);
cost.output = Some(0.0);
cost.cache_read = Some(0.0);
cost.cache_write = Some(0.0);
assert!(OfferingPricing::from_catalog_offering(&zero).is_some());
}
#[test]
fn absurd_catalog_prices_fail_closed_at_every_projection() {
let absurd = [
3_000_000.0,
MAX_PLAUSIBLE_PRICE_PER_MILLION + 1.0,
f64::MAX,
];
for price in absurd {
for field in 0..4 {
let mut offering = priced(CatalogSource::Bundled);
let cost = offering.cost.as_mut().expect("cost fixture");
match field {
0 => cost.input = Some(price),
1 => cost.output = Some(price),
2 => cost.cache_read = Some(price),
3 => cost.cache_write = Some(price),
_ => unreachable!(),
}
assert!(
!catalog_cost_is_valid(cost),
"field {field} accepted absurd price {price}"
);
assert!(
OfferingPricing::from_catalog_offering(&offering).is_none(),
"field {field} produced pricing from absurd price {price}"
);
assert_eq!(
route_pricing_sku(&offering),
PricingSku::UnknownOrStale,
"route projection accepted field {field} = {price}"
);
}
}
let mut expensive = priced(CatalogSource::Bundled);
let cost = expensive.cost.as_mut().expect("cost fixture");
cost.input = Some(600.0);
cost.output = Some(2_400.0);
assert!(
OfferingPricing::from_catalog_offering(&expensive).is_some(),
"a plausible frontier rate must survive the magnitude bound"
);
let mut boundary = priced(CatalogSource::Bundled);
let cost = boundary.cost.as_mut().expect("cost fixture");
cost.input = Some(MAX_PLAUSIBLE_PRICE_PER_MILLION);
assert!(OfferingPricing::from_catalog_offering(&boundary).is_some());
}
#[test]
fn live_source_carries_provider_live_provenance_and_effective_at() {
let src = CatalogSource::Live {
base_url_fingerprint: "fp".into(),
fetched_at: 1_700,
};
let p = OfferingPricing::from_catalog_offering(&priced(src)).expect("priced");
assert_eq!(p.provenance, PricingProvenance::ProviderLive);
assert_eq!(p.effective_at, Some(1_700));
assert_eq!(p.endpoint_fingerprint.as_deref(), Some("fp"));
}
#[test]
fn live_pricing_defect_gates_stale_and_mismatched_rows() {
let live = OfferingPricing::from_catalog_offering(&priced(CatalogSource::Live {
base_url_fingerprint: "route-fp".into(),
fetched_at: 1_000,
}))
.expect("priced");
assert_eq!(
live.live_pricing_defect(Some("route-fp"), Some(1_500), 1_000),
None
);
assert_eq!(
live.live_pricing_defect(Some("route-fp"), Some(2_000), 1_000),
Some(LivePricingDefect::Stale {
age_secs: 1_000,
max_age_secs: 1_000,
})
);
assert_eq!(
live.live_pricing_defect(Some("other-fp"), Some(1_500), 1_000),
Some(LivePricingDefect::EndpointMismatch {
row_fingerprint: "route-fp".into(),
route_fingerprint: "other-fp".into(),
})
);
assert_eq!(
live.live_pricing_defect(None, Some(1_500), 1_000),
Some(LivePricingDefect::UnknownRouteEndpoint)
);
assert_eq!(
live.live_pricing_defect(Some("route-fp"), None, 1_000),
Some(LivePricingDefect::MissingTimestamp)
);
for source in [CatalogSource::Bundled, CatalogSource::UserOverride] {
let row = OfferingPricing::from_catalog_offering(&priced(source)).expect("priced");
assert_eq!(row.live_pricing_defect(None, Some(u64::MAX), 1), None);
assert!(row.provenance.is_authoritative_without_freshness_check());
}
assert!(!PricingProvenance::ProviderLive.is_authoritative_without_freshness_check());
}
#[test]
fn live_row_without_a_fingerprint_is_never_authoritative() {
let mut live = OfferingPricing::from_catalog_offering(&priced(CatalogSource::Live {
base_url_fingerprint: "fp".into(),
fetched_at: 1_000,
}))
.expect("priced");
live.endpoint_fingerprint = None;
assert_eq!(
live.live_pricing_defect(Some("fp"), Some(1_001), 1_000),
Some(LivePricingDefect::MissingEndpointFingerprint)
);
let mismatch = LivePricingDefect::EndpointMismatch {
row_fingerprint: "a".into(),
route_fingerprint: "b".into(),
};
assert_eq!(mismatch.label(), "live_pricing_endpoint_mismatch");
let json = serde_json::to_string(&mismatch).expect("serialize defect");
assert!(!json.contains("http"), "{json}");
}
#[test]
fn no_cost_or_empty_cost_object_is_unknown() {
let mut offering = priced(CatalogSource::Bundled);
offering.cost = None;
assert!(
OfferingPricing::from_catalog_offering(&offering).is_none(),
"absent cost is unknown, not free"
);
offering.cost = Some(ModelsDevCost::default());
assert!(OfferingPricing::from_catalog_offering(&offering).is_none());
}
#[test]
fn estimate_cost_sums_priced_classes() {
let p = OfferingPricing::from_catalog_offering(&priced(CatalogSource::Bundled)).unwrap();
let usage = TokenUsage {
input: 1_000_000,
output: 500_000,
cache_read: 2_000_000,
cache_write: 0,
};
let cost = p.estimate_cost(&usage).expect("priced classes estimate");
assert!((cost - 0.546).abs() < 1e-9, "got {cost}");
}
#[test]
fn estimate_cost_is_none_when_a_used_class_is_unpriced() {
let p = OfferingPricing::from_catalog_offering(&priced(CatalogSource::Bundled)).unwrap();
let usage = TokenUsage {
input: 100,
output: 0,
cache_read: 0,
cache_write: 10,
};
assert!(p.estimate_cost(&usage).is_none());
}
#[test]
fn estimate_cost_with_zero_usage_is_zero() {
let p = OfferingPricing::from_catalog_offering(&priced(CatalogSource::Bundled)).unwrap();
assert_eq!(p.estimate_cost(&TokenUsage::default()), Some(0.0));
}
#[test]
fn finite_rates_that_overflow_the_computed_total_fail_closed() {
let pricing = OfferingPricing {
provider: "deepseek".to_string(),
wire_model_id: "deepseek-v4-pro".to_string(),
canonical_model: Some("deepseek-v4-pro".to_string()),
currency: Currency::Usd,
input_per_million: Some(f64::MAX),
output_per_million: None,
cache_read_per_million: None,
cache_write_per_million: None,
provenance: PricingProvenance::ModelsDevBundled,
effective_at: None,
endpoint_fingerprint: None,
};
let usage = TokenUsage {
input: u64::MAX,
..TokenUsage::default()
};
assert_eq!(pricing.estimate_cost(&usage), None);
let mut offering = priced(CatalogSource::Bundled);
offering.cost.as_mut().expect("cost fixture").input = Some(f64::MAX);
assert!(OfferingPricing::from_catalog_offering(&offering).is_none());
}
#[test]
fn route_pricing_sku_is_token_when_priced_and_unknown_otherwise() {
match route_pricing_sku(&priced(CatalogSource::Bundled)) {
PricingSku::Token {
input_per_mtok,
output_per_mtok,
} => {
assert_eq!(input_per_mtok, Some(0.28));
assert_eq!(output_per_mtok, Some(0.42));
}
other => panic!("expected Token, got {other:?}"),
}
let mut unpriced = priced(CatalogSource::Bundled);
unpriced.cost = None;
assert!(matches!(
route_pricing_sku(&unpriced),
PricingSku::UnknownOrStale
));
}
#[test]
fn currency_round_trips_including_other() {
for currency in [Currency::Usd, Currency::Cny, Currency::Other("eur".into())] {
let json = serde_json::to_string(¤cy).expect("serialize");
let back: Currency = serde_json::from_str(&json).expect("deserialize");
assert_eq!(currency, back);
}
}
#[test]
fn user_override_pricing_round_trips_and_carries_no_secrets() {
let pricing = OfferingPricing {
provider: "custom".into(),
wire_model_id: "house-model".into(),
canonical_model: None,
currency: Currency::Cny,
input_per_million: Some(8.0),
output_per_million: Some(16.0),
cache_read_per_million: None,
cache_write_per_million: None,
provenance: PricingProvenance::UserOverride,
effective_at: None,
endpoint_fingerprint: None,
};
let json = serde_json::to_string_pretty(&pricing).expect("serialize");
let back: OfferingPricing = serde_json::from_str(&json).expect("round-trip");
assert_eq!(pricing, back);
let lower = json.to_lowercase();
for needle in [
"api_key",
"apikey",
"authorization",
"secret",
"password",
"bearer",
"access_token",
] {
assert!(!lower.contains(needle), "pricing JSON contains `{needle}`");
}
}
#[test]
fn staleness_applies_to_live_rows_only() {
let live = CatalogSource::Live {
base_url_fingerprint: "fp".into(),
fetched_at: 1_000,
};
let live_price = OfferingPricing::from_catalog_offering(&priced(live)).unwrap();
assert!(!live_price.is_stale(1_500, 3_600), "within TTL");
assert!(live_price.is_stale(5_000, 3_600), "past TTL");
let bundled = OfferingPricing::from_catalog_offering(&priced(CatalogSource::Bundled)).unwrap();
assert!(!bundled.is_stale(u64::MAX, 1));
}
#[test]
fn pricing_flows_from_the_models_dev_parser() {
let raw = r#"{
"providers": {
"zai": {
"models": {
"glm-5.2": {
"id": "glm-5.2",
"modalities": { "input": ["text"], "output": ["text"] },
"cost": { "input": 1.4, "output": 4.4, "cache_read": 0.26 }
}
}
}
}
}"#;
let catalog = ModelsDevCatalog::parse_json(raw).expect("fixture parses");
let rows = bundled_offerings_from_models_dev(&catalog);
let pricing = OfferingPricing::from_catalog_offering(&rows[0]).expect("zai glm-5.2 is priced");
assert_eq!(pricing.provider, "zai");
assert_eq!(pricing.wire_model_id, "glm-5.2");
assert_eq!(pricing.input_per_million, Some(1.4));
assert_eq!(pricing.output_per_million, Some(4.4));
assert_eq!(pricing.cache_read_per_million, Some(0.26));
assert_eq!(pricing.provenance, PricingProvenance::ModelsDevBundled);
}
#[test]
fn cache_only_offering_is_unknown_at_the_route_layer() {
let mut offering = priced(CatalogSource::Bundled);
offering.cost = Some(ModelsDevCost {
input: None,
output: None,
cache_read: Some(0.028),
cache_write: None,
});
assert!(matches!(
route_pricing_sku(&offering),
PricingSku::UnknownOrStale
));
let pricing =
OfferingPricing::from_catalog_offering(&offering).expect("cache-only row is still priced");
assert!(pricing.has_any_price());
let usage = TokenUsage {
cache_read: 1_000_000,
..Default::default()
};
assert_eq!(pricing.estimate_cost(&usage), Some(0.028));
}
#[test]
fn user_override_source_maps_through_from_catalog_offering() {
let pricing = OfferingPricing::from_catalog_offering(&priced(CatalogSource::UserOverride))
.expect("priced");
assert_eq!(pricing.provenance, PricingProvenance::UserOverride);
assert_eq!(pricing.effective_at, None);
}
#[test]
fn staleness_is_inclusive_at_the_ttl_boundary() {
let live = CatalogSource::Live {
base_url_fingerprint: "fp".into(),
fetched_at: 1_000,
};
let p = OfferingPricing::from_catalog_offering(&priced(live)).unwrap();
assert!(p.is_stale(1_100, 100));
assert!(!p.is_stale(1_099, 100));
}
#[test]
fn unpriced_used_classes_names_exactly_what_makes_an_estimate_fail_closed() {
let pricing = OfferingPricing::from_catalog_offering(&priced(CatalogSource::Bundled))
.expect("priced row");
let no_write = TokenUsage {
input: 1_000_000,
output: 1_000_000,
cache_read: 1_000_000,
cache_write: 0,
};
assert!(pricing.unpriced_used_classes(&no_write).is_empty());
assert_eq!(pricing.estimate_cost(&no_write), Some(0.28 + 0.42 + 0.028));
let with_write = TokenUsage {
cache_write: 1,
..no_write
};
assert_eq!(
pricing.unpriced_used_classes(&with_write),
vec![TokenClass::CacheWrite]
);
assert_eq!(pricing.estimate_cost(&with_write), None);
let empty = TokenUsage::default();
assert!(pricing.unpriced_used_classes(&empty).is_empty());
assert_eq!(pricing.estimate_cost(&empty), Some(0.0));
}
#[test]
fn token_class_labels_and_counts_stay_aligned_with_token_usage() {
let usage = TokenUsage {
input: 1,
output: 2,
cache_read: 3,
cache_write: 4,
};
let seen: Vec<(&str, u64)> = TokenClass::ALL
.into_iter()
.map(|class| (class.label(), class.tokens(&usage)))
.collect();
assert_eq!(
seen,
vec![
("input", 1),
("output", 2),
("cache_read", 3),
("cache_write", 4),
]
);
}