use agentfit::{Fitter, Message, Strategy, Tokenizer};
struct ExactTokenizer;
impl Tokenizer for ExactTokenizer {
fn count(&self, text: &str) -> usize {
text.chars().count()
}
}
fn fitter(max_tokens: usize) -> Fitter {
Fitter::new(max_tokens)
.with_tokenizer(ExactTokenizer)
.with_per_message_overhead(0)
}
#[test]
fn under_budget_returns_unchanged() {
let msgs = vec![Message::user("hi")];
let kept = fitter(100).fit(msgs.clone(), Strategy::DropOldest);
assert_eq!(kept, msgs);
}
#[test]
fn drop_oldest_keeps_system_and_last_user() {
let msgs = vec![
Message::system("S"), Message::user("AAAAAAAAAAAA"), Message::assistant("BBBBBBBBBBBB"), Message::user("Q?"), ];
let kept = fitter(5).fit(msgs, Strategy::DropOldest);
assert_eq!(kept[0].role, "system");
assert_eq!(kept.last().unwrap().role, "user");
assert_eq!(kept.last().unwrap().content, "Q?");
assert!(kept.len() <= 3);
}
#[test]
fn drop_oldest_works_without_system() {
let msgs = vec![
Message::user("AAAAAAAAAAA"),
Message::assistant("BBBBBBBBBBB"),
Message::user("Q?"),
];
let kept = fitter(5).fit(msgs, Strategy::DropOldest);
assert_eq!(kept.last().unwrap().content, "Q?");
}
#[test]
fn drop_middle_preserves_recent_and_anchors() {
let msgs = vec![
Message::system("S"),
Message::user("U1"),
Message::assistant("A1"),
Message::user("U2"),
Message::assistant("A2"),
Message::user("Q?"),
];
let kept = fitter(8).fit(msgs, Strategy::DropMiddle);
assert_eq!(kept[0].role, "system");
assert_eq!(kept.last().unwrap().content, "Q?");
}
#[test]
fn truncate_largest_shrinks_a_message() {
let big = "X".repeat(40);
let msgs = vec![
Message::system("S"),
Message::user(big),
Message::user("Q?"),
];
let kept = fitter(15).fit(msgs, Strategy::TruncateLargest);
assert_eq!(kept[0].role, "system");
assert_eq!(kept.last().unwrap().content, "Q?");
assert!(kept[1].content.len() < 40);
assert!(kept[1].content.contains("[truncated]"));
}
#[test]
fn count_includes_per_message_overhead() {
let f = Fitter::new(0)
.with_tokenizer(ExactTokenizer)
.with_per_message_overhead(3);
let msgs = vec![Message::user("hi"), Message::user("ho")];
assert_eq!(f.count(&msgs), 10);
}
#[test]
fn anchors_only_returned_if_below_anchors_budget() {
let msgs = vec![
Message::system("Lorem ipsum"),
Message::user("very long question that exceeds budget"),
];
let kept = fitter(5).fit(msgs.clone(), Strategy::DropOldest);
assert_eq!(kept, msgs);
}
#[test]
fn char_approx_default_works() {
let f = Fitter::new(2);
let msgs = vec![Message::user("abcd"), Message::user("efgh")];
let kept = f.fit(msgs, Strategy::DropOldest);
assert_eq!(kept.last().unwrap().content, "efgh");
}