use std::path::PathBuf;
use candle_core::Device;
use super::tiny;
use crate::tokenizer::PadToken;
use crate::tokenizer::TextTokenizer;
fn markers_path() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/tiny_tokenizer_markers.json")
}
#[test]
fn fixed_length_padding_pads_every_row_to_the_requested_width_with_mask() {
let tokenizer = TextTokenizer::from_file_fixed_length(
&markers_path(),
8,
PadToken::Named("[MASK]".to_string()),
)
.unwrap();
let batch = tokenizer.encode(&["hello"], &Device::Cpu).unwrap();
assert_eq!(batch.input_ids.dims(), &[1, 8]);
assert_eq!(
batch.input_ids.to_vec2::<u32>().unwrap()[0],
vec![2, 4, 3, 18, 18, 18, 18, 18],
"3 real tokens (CLS, hello, SEP) then [MASK] filling the rest"
);
assert_eq!(
batch.attention_mask.to_vec2::<u32>().unwrap()[0],
vec![1, 1, 1, 0, 0, 0, 0, 0],
"the [MASK]-filled tail is unattendable, exactly like ordinary padding"
);
}
#[test]
fn an_unregistered_marker_shatters_instead_of_tokenizing_as_one_piece() {
let tokenizer = tiny(16);
let ids = tokenizer
.encode(&["[unused0] hello"], &Device::Cpu)
.unwrap()
.input_ids
.to_vec2::<u32>()
.unwrap();
assert!(
!ids[0].contains(&16),
"id 16 ([unused0]) must not appear from unregistered text: {:?}",
ids[0]
);
assert!(
ids[0].contains(&1),
"the shattered pieces fall back to [UNK]: {:?}",
ids[0]
);
}
#[test]
fn a_registered_marker_tokenizes_as_one_piece_with_the_trailing_space_intact() {
let mut tokenizer = TextTokenizer::from_file(&markers_path(), 16, PadToken::Id(0)).unwrap();
tokenizer.register_special_tokens(&["[unused0]"]).unwrap();
let ids = tokenizer
.encode(&["[unused0] hello"], &Device::Cpu)
.unwrap()
.input_ids
.to_vec2::<u32>()
.unwrap();
assert_eq!(
ids[0],
vec![2, 16, 4, 3],
"CLS, [unused0], hello, SEP — one piece for the marker, not several"
);
}
#[test]
fn a_registered_marker_tokenizes_identically_whether_or_not_the_following_text_had_its_own_space() {
let mut tokenizer = TextTokenizer::from_file(&markers_path(), 16, PadToken::Id(0)).unwrap();
tokenizer.register_special_tokens(&["[unused0]"]).unwrap();
let spaced = tokenizer
.encode(&["[unused0] hello"], &Device::Cpu)
.unwrap()
.input_ids
.to_vec2::<u32>()
.unwrap()[0]
.clone();
let unspaced = tokenizer
.encode(&["[unused0]hello"], &Device::Cpu)
.unwrap()
.input_ids
.to_vec2::<u32>()
.unwrap()[0]
.clone();
assert_eq!(spaced, vec![2, 16, 4, 3]);
assert_eq!(
spaced, unspaced,
"this crate's added-token matching does not need the space to recover [unused0] as one piece; \
the pipeline still builds the spaced string to match the reference's own literal prompt"
);
}