use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct TokenUsage {
pub input_tokens: u32,
pub output_tokens: u32,
pub total_tokens: u32,
pub cached_tokens: Option<u32>,
pub reasoning_tokens: Option<u32>,
pub audio_tokens: Option<u32>,
}
impl TokenUsage {
pub fn new(input_tokens: u32, output_tokens: u32) -> Self {
Self {
input_tokens,
output_tokens,
total_tokens: input_tokens + output_tokens,
cached_tokens: None,
reasoning_tokens: None,
audio_tokens: None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_token_usage() {
let usage = TokenUsage::new(100, 50);
assert_eq!(usage.input_tokens, 100);
assert_eq!(usage.output_tokens, 50);
assert_eq!(usage.total_tokens, 150);
}
#[test]
fn test_token_usage_default() {
let usage = TokenUsage::default();
assert_eq!(usage.input_tokens, 0);
assert_eq!(usage.output_tokens, 0);
assert_eq!(usage.total_tokens, 0);
assert!(usage.cached_tokens.is_none());
assert!(usage.reasoning_tokens.is_none());
assert!(usage.audio_tokens.is_none());
}
#[test]
fn test_token_usage_zero_tokens() {
let usage = TokenUsage::new(0, 0);
assert_eq!(usage.total_tokens, 0);
}
#[test]
fn test_token_usage_large_values() {
let usage = TokenUsage::new(100_000, 50_000);
assert_eq!(usage.total_tokens, 150_000);
}
#[test]
fn test_token_usage_max_values() {
let usage = TokenUsage::new(u32::MAX / 2, u32::MAX / 2);
assert_eq!(usage.total_tokens, u32::MAX - 1);
}
#[test]
fn test_token_usage_with_cached_tokens() {
let mut usage = TokenUsage::new(100, 50);
usage.cached_tokens = Some(25);
assert_eq!(usage.cached_tokens, Some(25));
}
#[test]
fn test_token_usage_with_reasoning_tokens() {
let mut usage = TokenUsage::new(100, 50);
usage.reasoning_tokens = Some(30);
assert_eq!(usage.reasoning_tokens, Some(30));
}
#[test]
fn test_token_usage_with_audio_tokens() {
let mut usage = TokenUsage::new(100, 50);
usage.audio_tokens = Some(20);
assert_eq!(usage.audio_tokens, Some(20));
}
#[test]
fn test_token_usage_with_all_optional_fields() {
let mut usage = TokenUsage::new(1000, 500);
usage.cached_tokens = Some(100);
usage.reasoning_tokens = Some(200);
usage.audio_tokens = Some(50);
assert_eq!(usage.cached_tokens, Some(100));
assert_eq!(usage.reasoning_tokens, Some(200));
assert_eq!(usage.audio_tokens, Some(50));
}
#[test]
fn test_token_usage_serialization() {
let usage = TokenUsage::new(100, 50);
let json = serde_json::to_value(&usage).unwrap();
assert_eq!(json["input_tokens"], 100);
assert_eq!(json["output_tokens"], 50);
assert_eq!(json["total_tokens"], 150);
}
#[test]
fn test_token_usage_deserialization() {
let json = r#"{
"input_tokens": 200,
"output_tokens": 100,
"total_tokens": 300,
"cached_tokens": 50,
"reasoning_tokens": null,
"audio_tokens": null
}"#;
let usage: TokenUsage = serde_json::from_str(json).unwrap();
assert_eq!(usage.input_tokens, 200);
assert_eq!(usage.output_tokens, 100);
assert_eq!(usage.total_tokens, 300);
assert_eq!(usage.cached_tokens, Some(50));
}
#[test]
fn test_token_usage_deserialization_minimal() {
let json = r#"{
"input_tokens": 10,
"output_tokens": 5,
"total_tokens": 15
}"#;
let usage: TokenUsage = serde_json::from_str(json).unwrap();
assert_eq!(usage.input_tokens, 10);
assert!(usage.cached_tokens.is_none());
}
#[test]
fn test_token_usage_roundtrip() {
let mut original = TokenUsage::new(500, 250);
original.cached_tokens = Some(100);
original.reasoning_tokens = Some(50);
let json = serde_json::to_string(&original).unwrap();
let restored: TokenUsage = serde_json::from_str(&json).unwrap();
assert_eq!(original.input_tokens, restored.input_tokens);
assert_eq!(original.output_tokens, restored.output_tokens);
assert_eq!(original.cached_tokens, restored.cached_tokens);
assert_eq!(original.reasoning_tokens, restored.reasoning_tokens);
}
#[test]
fn test_token_usage_clone() {
let mut original = TokenUsage::new(100, 50);
original.cached_tokens = Some(25);
let cloned = original.clone();
assert_eq!(original.input_tokens, cloned.input_tokens);
assert_eq!(original.output_tokens, cloned.output_tokens);
assert_eq!(original.cached_tokens, cloned.cached_tokens);
}
#[test]
fn test_token_usage_input_only() {
let usage = TokenUsage::new(100, 0);
assert_eq!(usage.total_tokens, 100);
}
#[test]
fn test_token_usage_output_only() {
let usage = TokenUsage::new(0, 100);
assert_eq!(usage.total_tokens, 100);
}
}