use super::*;
fn expected(pairs: &[(&str, u32)], doc_len: u32) -> SparseEmbedding {
SparseEmbedding::from_pairs(
pairs
.iter()
.map(|&(stem, count)| (bm25_hash(stem), term_frequency::saturation(count, doc_len))),
)
}
#[test]
fn short_fixture_matches_the_reference() {
let stopwords = test_stopwords();
let got = embed_document("The quick brown fox jumps over the lazy dog.", &stopwords);
let want = expected(
&[
("brown", 1),
("dog", 1),
("fox", 1),
("jump", 1),
("lazi", 1),
("quick", 1),
],
6,
);
assert_eq!(got, want);
}
#[test]
fn empty_and_whitespace_fixtures_produce_empty_rows() {
let stopwords = test_stopwords();
assert!(embed_document("", &stopwords).is_empty());
assert!(embed_document(" \n\t ", &stopwords).is_empty());
}
#[test]
fn code_fixture_matches_the_reference_including_repeated_tokens() {
let stopwords = test_stopwords();
let text = "fn main() { let xs: Vec<f32> = (0..10).map(|i| i as f32 * 0.5).collect(); println!(\"{:?}\", xs); }";
let got = embed_document(text, &stopwords);
let want = expected(
&[
("0", 2),
("10", 1),
("5", 1),
("collect", 1),
("f32", 2),
("fn", 1),
("let", 1),
("main", 1),
("map", 1),
("println", 1),
("vec", 1),
("xs", 2),
],
15,
);
assert_eq!(got, want);
}
#[test]
fn batch_a_fixture_matches_the_reference() {
let stopwords = test_stopwords();
let got = embed_document("Embeddings map text to vectors.", &stopwords);
let want = expected(&[("embed", 1), ("map", 1), ("text", 1), ("vector", 1)], 4);
assert_eq!(got, want);
}
#[test]
fn batch_c_fixture_matches_the_reference() {
let stopwords = test_stopwords();
let got = embed_document("Short.", &stopwords);
let want = expected(&[("short", 1)], 1);
assert_eq!(got, want);
}
#[test]
fn a_lone_underscore_is_dropped_by_the_punctuation_filter() {
let stopwords = test_stopwords();
let got = embed_document("hello _ world", &stopwords);
let want = expected(&[("hello", 1), ("world", 1)], 2);
assert_eq!(got, want);
}
#[test]
fn the_length_cap_keeps_exactly_forty_characters_and_drops_forty_one() {
let stopwords = test_stopwords();
let text = format!("a {} b {} c", "x".repeat(41), "y".repeat(40));
let got = embed_document(&text, &stopwords);
let want = expected(
&[
("b", 1),
("c", 1),
("yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyi", 1),
],
3,
);
assert_eq!(got, want);
}
#[test]
fn stemming_and_stopwords_are_case_insensitive() {
let stopwords = test_stopwords();
let got = embed_document("The RUNNING Runner ran QUICKLY", &stopwords);
let want = expected(&[("quick", 1), ("ran", 1), ("run", 1), ("runner", 1)], 4);
assert_eq!(got, want);
}
#[test]
fn a_possessive_apostrophe_splits_into_two_tokens_and_the_fragment_is_a_real_stopword() {
let stopwords = test_stopwords();
assert!(stopwords.contains("s"));
let got = embed_document("the model's parameters", &stopwords);
let want = expected(&[("model", 1), ("paramet", 1)], 2);
assert_eq!(got, want);
}
#[test]
fn multilingual_fixture_reaches_no_stopword_or_punctuation_path_and_keeps_every_token() {
let stopwords = test_stopwords();
let text = "Árvíztűrő tükörfúrógép — 東京タワーは高いです。Ça va très bien, merci!";
let got = embed_document(text, &stopwords);
let want = expected(
&[
("árvíztűrő", 1),
("tükörfúrógép", 1),
("東京タワーは高いです", 1),
("ça", 1),
("va", 1),
("très", 1),
("bien", 1),
("merci", 1),
],
8,
);
assert_eq!(got, want);
}
#[test]
fn query_path_hashes_unique_stems_at_a_uniform_weight() {
let stopwords = test_stopwords();
let got = embed_query("dog dog cat", &stopwords);
let want = SparseEmbedding::from_pairs([(bm25_hash("dog"), 1.0f32), (bm25_hash("cat"), 1.0f32)]);
assert_eq!(got, want);
assert_eq!(
got.len(),
2,
"a repeated stem contributes one entry, not two"
);
}
#[test]
fn query_path_shares_the_same_filters_as_the_document_path() {
let stopwords = test_stopwords();
let got = embed_query("the _ dog", &stopwords);
let want = SparseEmbedding::from_pairs([(bm25_hash("dog"), 1.0f32)]);
assert_eq!(got, want);
}
#[test]
fn a_stem_repeated_across_a_document_shares_one_weight_scaled_by_saturation() {
let stopwords = test_stopwords();
let got = embed_document("alpha beta alpha gamma alpha", &stopwords);
let want = expected(&[("alpha", 3), ("beta", 1), ("gamma", 1)], 5);
assert_eq!(got, want);
assert_ne!(
term_frequency::saturation(3, 5),
term_frequency::saturation(1, 5),
"a thrice-repeated stem must not collapse to the same weight as a once-only one"
);
}