use super::*;
use chrono::{Local, TimeZone};
fn entry(app: AppKind, model: &str, created_at: i64) -> UsageEntry {
UsageEntry::new(app, model.to_string(), None, created_at, 10, 20, 5, 3, None)
}
fn local_noon(year: i32, month: u32, day: u32) -> i64 {
Local
.with_ymd_and_hms(year, month, day, 12, 0, 0)
.single()
.unwrap()
.timestamp()
}
#[test]
fn test_build_rows_by_app() {
let entries = vec![
entry(AppKind::Claude, "m", local_noon(2026, 9, 1)),
entry(AppKind::Codex, "m", local_noon(2026, 9, 1)),
entry(AppKind::Codex, "m", local_noon(2026, 9, 1)),
];
let rows = build_rows(&entries, GroupBy::App);
assert_eq!(rows.len(), 2);
assert_eq!(rows[0].0, "claude");
assert_eq!(rows[0].1.requests, 1);
assert_eq!(rows[1].0, "codex");
assert_eq!(rows[1].1.requests, 2);
}
#[test]
fn test_build_rows_by_model() {
let entries = vec![
entry(AppKind::Claude, "claude-sonnet-4", local_noon(2026, 9, 1)),
entry(AppKind::Codex, "gpt-5", local_noon(2026, 9, 1)),
];
let rows = build_rows(&entries, GroupBy::Model);
assert_eq!(rows.len(), 2);
assert_eq!(rows[0].0, "claude/claude-sonnet-4");
assert_eq!(rows[1].0, "codex/gpt-5");
}
#[test]
fn test_build_rows_by_day() {
let entries = vec![
entry(AppKind::Claude, "m", local_noon(2026, 9, 1)),
entry(AppKind::Claude, "m", local_noon(2026, 9, 1) + 3600),
entry(AppKind::Claude, "m", local_noon(2026, 9, 3)),
];
let rows = build_rows(&entries, GroupBy::Day);
assert_eq!(rows.len(), 2);
assert_eq!(rows[0].0, "2026-09-01");
assert_eq!(rows[0].1.requests, 2);
assert_eq!(rows[1].0, "2026-09-03");
}
#[test]
fn test_resolve_threads() {
assert_eq!(resolve_threads(None), None);
assert_eq!(resolve_threads(Some(0)), None);
assert_eq!(resolve_threads(Some(1)), Some(1));
assert_eq!(resolve_threads(Some(16)), Some(16));
assert_eq!(resolve_threads(Some(120000)), Some(16));
}