use crate::budgets::BudgetSpend;
use crate::spend::{Cost, Prices};
use serde_json::json;
#[test]
fn a_malformed_table_degrades_row_by_row() {
let prices = Prices::from_json(&json!({
"opus": { "input": 3, "output": "nope", "cache_read": -5 },
"broken": "not an object",
}));
assert!(prices.of(Some("broken")).is_none());
assert!(prices.of(Some("absent")).is_none());
assert!(prices.of(None).is_none());
let price = prices.of(Some("opus")).unwrap();
assert_eq!(price.input, 3_000_000);
assert_eq!(price.output, 0, "a non-numeric rate reads zero");
assert_eq!(price.cache_read, 0, "a negative rate reads zero");
assert!(Prices::from_json(&json!([1, 2])).is_empty());
}
#[test]
fn money_renders_at_cent_resolution_without_conflating_small_with_none() {
assert_eq!(Cost::default().usd(), "$0.00");
assert_eq!(
Cost {
micro_usd: 5_000,
unpriced_tokens: 0
}
.usd(),
"<$0.01"
);
assert_eq!(
Cost {
micro_usd: 10_000,
unpriced_tokens: 0
}
.usd(),
"$0.01"
);
assert_eq!(
Cost {
micro_usd: 1_234_567,
unpriced_tokens: 0
}
.usd(),
"$1.23"
);
}
#[test]
fn a_contained_cached_slice_is_priced_once_and_the_partition_is_exhaustive() {
let price = Prices::from_json(
&json!({ "opus": { "input": 2, "output": 8, "cache_read": 0.2, "cache_write": 2.5 } }),
)
.of(Some("opus"))
.unwrap();
let contained = BudgetSpend {
input_tokens: 1_000_000,
output_tokens: 100_000,
cache_read_tokens: 900_000,
cache_write_tokens: 0,
};
assert_eq!(price.cost(contained), 1_180_000);
let disjoint = BudgetSpend {
input_tokens: 100_000,
output_tokens: 0,
cache_read_tokens: 900_000,
cache_write_tokens: 200_000,
};
assert_eq!(price.cost(disjoint), 680_000);
let uncached = BudgetSpend {
input_tokens: 500_000,
output_tokens: 100_000,
..BudgetSpend::default()
};
assert_eq!(price.cost(uncached), 1_800_000);
let flat = Prices::from_json(
&json!({ "m": { "input": 1, "output": 1, "cache_read": 1, "cache_write": 1 } }),
)
.of(Some("m"))
.unwrap();
for s in [contained, disjoint, uncached] {
assert_eq!(flat.cost(s), s.total_tokens(), "{s:?}");
}
}
#[test]
fn a_nonsense_rate_saturates_rather_than_wrapping() {
let prices = Prices::from_json(&json!({ "opus": { "input": 1e300 } }));
let price = prices.of(Some("opus")).unwrap();
let cost = price.cost(BudgetSpend {
input_tokens: u64::MAX,
..BudgetSpend::default()
});
assert!(cost > 0, "saturating, never a wrap to a small figure");
}