#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TraceTokVerdict {
Pass,
Fail,
}
#[derive(Debug, Clone, Copy)]
pub struct Span {
pub started: bool,
pub ended: bool,
pub start_ts: i64,
pub end_ts: i64,
}
#[must_use]
pub fn verdict_from_no_orphan_spans(spans: &[Span]) -> TraceTokVerdict {
if spans.is_empty() {
return TraceTokVerdict::Fail;
}
for s in spans {
if s.started && !s.ended {
return TraceTokVerdict::Fail;
}
if s.started && s.start_ts > s.end_ts {
return TraceTokVerdict::Fail;
}
}
TraceTokVerdict::Pass
}
#[must_use]
pub fn verdict_from_parent_child_ordering(parent: Span, child: Span) -> TraceTokVerdict {
if !parent.ended || !child.ended {
return TraceTokVerdict::Fail;
}
if child.start_ts >= parent.start_ts && child.end_ts <= parent.end_ts {
TraceTokVerdict::Pass
} else {
TraceTokVerdict::Fail
}
}
#[must_use]
pub fn verdict_from_bpe_roundtrip(original: &str, roundtrip: &str) -> TraceTokVerdict {
let norm = |s: &str| s.split_whitespace().collect::<Vec<_>>().join(" ");
if norm(original) == norm(roundtrip) {
TraceTokVerdict::Pass
} else {
TraceTokVerdict::Fail
}
}
#[must_use]
pub fn verdict_from_special_token_detection(
bos_in_config: bool,
bos_id: Option<u32>,
eos_in_config: bool,
eos_id: Option<u32>,
) -> TraceTokVerdict {
if bos_in_config && bos_id.is_none() {
return TraceTokVerdict::Fail;
}
if eos_in_config && eos_id.is_none() {
return TraceTokVerdict::Fail;
}
TraceTokVerdict::Pass
}
#[must_use]
pub fn verdict_from_gguf_vocab_matches(
gguf_vocab_size: u32,
tokenizer_json_vocab_size: u32,
) -> TraceTokVerdict {
if gguf_vocab_size == 0 || tokenizer_json_vocab_size == 0 {
return TraceTokVerdict::Fail;
}
if gguf_vocab_size == tokenizer_json_vocab_size {
TraceTokVerdict::Pass
} else {
TraceTokVerdict::Fail
}
}
#[cfg(test)]
mod tests {
use super::*;
fn span(started: bool, ended: bool, start: i64, end: i64) -> Span {
Span {
started,
ended,
start_ts: start,
end_ts: end,
}
}
#[test]
fn ftrace001_pass_all_started_and_ended() {
let spans = vec![
span(true, true, 0, 100),
span(true, true, 100, 200),
];
let v = verdict_from_no_orphan_spans(&spans);
assert_eq!(v, TraceTokVerdict::Pass);
}
#[test]
fn ftrace001_fail_orphan_span() {
let spans = vec![span(true, false, 0, 0)];
let v = verdict_from_no_orphan_spans(&spans);
assert_eq!(v, TraceTokVerdict::Fail);
}
#[test]
fn ftrace001_fail_inverted_timestamps() {
let spans = vec![span(true, true, 200, 100)];
let v = verdict_from_no_orphan_spans(&spans);
assert_eq!(v, TraceTokVerdict::Fail);
}
#[test]
fn ftrace001_fail_empty() {
let v = verdict_from_no_orphan_spans(&[]);
assert_eq!(v, TraceTokVerdict::Fail);
}
#[test]
fn ftrace002_pass_child_inside_parent() {
let parent = span(true, true, 0, 1000);
let child = span(true, true, 100, 800);
let v = verdict_from_parent_child_ordering(parent, child);
assert_eq!(v, TraceTokVerdict::Pass);
}
#[test]
fn ftrace002_pass_child_at_boundaries() {
let parent = span(true, true, 0, 1000);
let child = span(true, true, 0, 1000);
let v = verdict_from_parent_child_ordering(parent, child);
assert_eq!(v, TraceTokVerdict::Pass);
}
#[test]
fn ftrace002_fail_child_starts_before_parent() {
let parent = span(true, true, 100, 1000);
let child = span(true, true, 50, 800);
let v = verdict_from_parent_child_ordering(parent, child);
assert_eq!(v, TraceTokVerdict::Fail);
}
#[test]
fn ftrace002_fail_child_ends_after_parent() {
let parent = span(true, true, 0, 500);
let child = span(true, true, 100, 800);
let v = verdict_from_parent_child_ordering(parent, child);
assert_eq!(v, TraceTokVerdict::Fail);
}
#[test]
fn ftrace002_fail_unended_parent() {
let parent = span(true, false, 0, 0);
let child = span(true, true, 100, 800);
let v = verdict_from_parent_child_ordering(parent, child);
assert_eq!(v, TraceTokVerdict::Fail);
}
#[test]
fn ftok001_pass_simple_roundtrip() {
let v = verdict_from_bpe_roundtrip("Hello world", "Hello world");
assert_eq!(v, TraceTokVerdict::Pass);
}
#[test]
fn ftok001_pass_whitespace_normalized() {
let v = verdict_from_bpe_roundtrip("Hello world", "Hello world");
assert_eq!(v, TraceTokVerdict::Pass);
}
#[test]
fn ftok001_fail_token_drift() {
let v = verdict_from_bpe_roundtrip("Hello world", "Goodbye world");
assert_eq!(v, TraceTokVerdict::Fail);
}
#[test]
fn ftok001_fail_truncation() {
let v = verdict_from_bpe_roundtrip("Hello world how are you", "Hello world");
assert_eq!(v, TraceTokVerdict::Fail);
}
#[test]
fn ftok002_pass_bos_eos_detected() {
let v = verdict_from_special_token_detection(true, Some(1), true, Some(2));
assert_eq!(v, TraceTokVerdict::Pass);
}
#[test]
fn ftok002_pass_no_special_tokens_in_config() {
let v = verdict_from_special_token_detection(false, None, false, None);
assert_eq!(v, TraceTokVerdict::Pass);
}
#[test]
fn ftok002_fail_bos_in_config_but_not_found() {
let v = verdict_from_special_token_detection(true, None, true, Some(2));
assert_eq!(v, TraceTokVerdict::Fail);
}
#[test]
fn ftok002_fail_eos_in_config_but_not_found() {
let v = verdict_from_special_token_detection(true, Some(1), true, None);
assert_eq!(v, TraceTokVerdict::Fail);
}
#[test]
fn ftok003_pass_qwen2_vocab() {
let v = verdict_from_gguf_vocab_matches(151_936, 151_936);
assert_eq!(v, TraceTokVerdict::Pass);
}
#[test]
fn ftok003_fail_drift() {
let v = verdict_from_gguf_vocab_matches(151_936, 32_000);
assert_eq!(v, TraceTokVerdict::Fail);
}
#[test]
fn ftok003_fail_zero_gguf() {
let v = verdict_from_gguf_vocab_matches(0, 32_000);
assert_eq!(v, TraceTokVerdict::Fail);
}
#[test]
fn ftok003_fail_zero_json() {
let v = verdict_from_gguf_vocab_matches(32_000, 0);
assert_eq!(v, TraceTokVerdict::Fail);
}
#[test]
fn mutation_survey_002_containment_table() {
let parent = span(true, true, 0, 1000);
let cases = [
((0_i64, 500_i64), TraceTokVerdict::Pass),
((500, 1000), TraceTokVerdict::Pass),
((0, 1000), TraceTokVerdict::Pass),
((-1, 999), TraceTokVerdict::Fail), ((1, 1001), TraceTokVerdict::Fail), ((0, 1500), TraceTokVerdict::Fail), ];
for ((s, e), expected) in cases {
let child = span(true, true, s, e);
let v = verdict_from_parent_child_ordering(parent, child);
assert_eq!(v, expected, "child=({s}, {e})");
}
}
#[test]
fn realistic_healthy_passes_all_5() {
let v1 = verdict_from_no_orphan_spans(&[
span(true, true, 0, 100),
span(true, true, 50, 80),
]);
let v2 = verdict_from_parent_child_ordering(
span(true, true, 0, 100),
span(true, true, 50, 80),
);
let v3 = verdict_from_bpe_roundtrip("What is 2+2?", "What is 2+2?");
let v4 = verdict_from_special_token_detection(true, Some(151643), true, Some(151645));
let v5 = verdict_from_gguf_vocab_matches(151_936, 151_936);
for v in [v1, v2, v3, v4, v5] {
assert_eq!(v, TraceTokVerdict::Pass);
}
}
#[test]
fn realistic_pre_fix_all_5_failures() {
let v1 = verdict_from_no_orphan_spans(&[span(true, false, 0, 0)]);
let v2 = verdict_from_parent_child_ordering(
span(true, true, 100, 200),
span(true, true, 50, 800), );
let v3 = verdict_from_bpe_roundtrip("What is 2+2?", "Goodbye world");
let v4 = verdict_from_special_token_detection(true, None, true, Some(151645));
let v5 = verdict_from_gguf_vocab_matches(151_936, 32_000);
for v in [v1, v2, v3, v4, v5] {
assert_eq!(v, TraceTokVerdict::Fail);
}
}
}