1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
//! The per-token prefill fallback must be *audible*.
//!
//! `warn_unbatchable` exists because a silent fallback costs ~4x prefill and is
//! otherwise invisible — the numbers are simply worse, with nothing to point at.
//! It emits through `tracing::warn!`, and `cargo test` installs no subscriber, so
//! the warning that guards against a silent regression was itself silent under
//! test. The LFM2 K-quant parity suite spent a release reporting a vacuous
//! `cosine=1.000000` (comparing the per-token path against itself) while this
//! warning fired into the void on every run.
//!
//! This installs a capturing subscriber and asserts the warning actually fires
//! when the batched path declines, so a future change that makes the fallback
//! silent fails here instead of in someone's throughput numbers.
//!
//! `CERA_CPU_TIER=scalar` is the lever: it caps the tier below `Avx2`, so
//! `int8_gemm_available()` is false, `batched_gemm_supports` declines every
//! dtype, and prefill must fall back. The tier is cached in a `OnceLock` and read
//! once per process, which is why this is its own test binary with a single test.
//!
//! The lever used to be `avx512`, which worked while the x86 int8 GEMM required
//! VNNI. The AVX2 kernels made every tier from `Avx2` up capable, so `scalar` is
//! now the only x86 tier that forces the fallback this test needs.
#![cfg(all(target_arch = "x86_64", not(has_blas)))]
use std::sync::{Arc, Mutex};
use tracing_subscriber::layer::SubscriberExt;
/// Collects the `message` field of every `WARN` event, from any target.
///
/// Debug-formatted rather than fully rendered — the assertion only needs a
/// substring match, and reaching for a real formatter here would pull in
/// machinery the test does not use. No target filter on purpose: the point is
/// to prove *something* warned about the fallback, so narrowing to
/// `cera::model::transformer` would bake this test's expectation into where the
/// warning happens to live.
#[derive(Clone, Default)]
struct WarnCapture(Arc<Mutex<Vec<String>>>);
impl<S: tracing::Subscriber> tracing_subscriber::Layer<S> for WarnCapture {
fn on_event(
&self,
event: &tracing::Event<'_>,
_ctx: tracing_subscriber::layer::Context<'_, S>,
) {
if *event.metadata().level() != tracing::Level::WARN {
return;
}
// The message is a field, not something `Event` exposes directly; a
// visitor is the only way to read it back out.
struct Msg<'a>(&'a mut String);
impl tracing::field::Visit for Msg<'_> {
fn record_debug(&mut self, field: &tracing::field::Field, value: &dyn std::fmt::Debug) {
if field.name() == "message" {
self.0.push_str(&format!("{value:?}"));
}
}
}
let mut msg = String::new();
event.record(&mut Msg(&mut msg));
if !msg.is_empty() {
self.0.lock().unwrap_or_else(|p| p.into_inner()).push(msg);
}
}
}
/// `#[ignore]` like the other fixture-backed tests: the mainline
/// `cargo test --workspace` job has no GGUFs, and a test that silently skips
/// there would report the same green as one that ran. The parity job fetches
/// fixtures and runs this explicitly with `--ignored`.
#[test]
#[ignore = "needs a GGUF fixture; run with --ignored"]
fn per_token_fallback_emits_a_warning() {
// SAFETY: single-threaded, first thing in the process to touch the
// environment, and set before any `cpu_features()` call — the tier is
// cached, so this binary holds exactly one test.
unsafe {
std::env::set_var("CERA_CPU_TIER", "scalar");
}
let tier = cera::backend::cpu_features::cpu_features().tier;
assert!(
tier < cera::backend::cpu_features::CpuTier::Avx2,
"CERA_CPU_TIER=scalar did not downgrade the tier (got {tier:?}); without \
the downgrade the batched path would still run and this test would be \
asserting nothing"
);
assert!(
!cera::backend::cpu::int8_gemm_available(),
"int8 GEMM still reports available at tier {tier:?} — the fallback this \
test needs would not trigger"
);
let capture = WarnCapture::default();
let subscriber = tracing_subscriber::registry().with(capture.clone());
let _guard = tracing::subscriber::set_default(subscriber);
// Drive a real fallback. `warn_unbatchable` is `pub(crate)`, so this goes
// through the public surface that a user would hit: a Q4_0 model whose
// batched path declines for lack of an int8 kernel.
let Some(path) = find_fixture("target/oracle/models/SmolLM-135M.Q4_0.gguf") else {
// A skip that reports PASS is how a gate goes green forever without
// running — the failure mode this whole test exists to prevent.
// `CERA_REQUIRE_MODEL=1` turns that skip into a failure, for a caller
// who knows the fixture should be there.
//
// CI does NOT set it, deliberately: the parity leg fetches only the
// `core` set on a PR, and the variable is all-or-nothing, so it would
// fail the arch-tier tests that are supposed to skip. What guards CI is
// upstream instead — `fetch_test_models.sh` exits non-zero if a download
// fails, so a fixture cannot go quietly missing there. Mirrors the
// parity suites, including their reason for not wiring it into CI.
assert!(
std::env::var("CERA_REQUIRE_MODEL").is_err(),
"CERA_REQUIRE_MODEL is set but the fixture is absent: \
target/oracle/models/SmolLM-135M.Q4_0.gguf (run \
scripts/fetch_test_models.sh, or set CERA_MODEL_ROOT)"
);
eprintln!("[warn-test] SKIP: fixture absent (scripts/fetch_test_models.sh)");
return;
};
let gguf = cera::gguf::GgufFile::open(&path).expect("open fixture");
let model = cera::model::load_model(gguf, None, 2048).expect("load fixture");
let mut state =
cera::kv_cache::InferenceState::from_config(model.config()).expect("inference state");
// >1 token, or the batched path is never even considered.
let _ = model.forward_prefill(&[1, 415, 2323, 302, 4843, 349, 264, 2818], 0, &mut state);
let warnings = capture.0.lock().unwrap_or_else(|p| p.into_inner()).clone();
assert!(
warnings
.iter()
.any(|w| w.contains("fell back to the per-token path")),
"prefill fell back but emitted no warning — a silent ~4x regression. \
Captured warnings: {warnings:?}"
);
}
/// Mirrors the parity suites' fixture resolution: crate dir's parent, cwd, then
/// `CERA_MODEL_ROOT`.
fn find_fixture(rel: &str) -> Option<std::path::PathBuf> {
let mut roots: Vec<std::path::PathBuf> = Vec::new();
if let Ok(manifest) = std::env::var("CARGO_MANIFEST_DIR")
&& let Some(parent) = std::path::PathBuf::from(&manifest).parent()
{
roots.push(parent.to_path_buf());
}
if let Ok(cwd) = std::env::current_dir() {
roots.push(cwd);
}
if let Ok(root) = std::env::var("CERA_MODEL_ROOT") {
roots.push(std::path::PathBuf::from(root));
}
roots.into_iter().map(|r| r.join(rel)).find(|p| p.exists())
}