#![allow(clippy::disallowed_methods)]
#![cfg(feature = "model-tests")]
#[test]
fn stress_max_tokens_one() {
let model_path = match std::env::var("TEST_MODEL_PATH") {
Ok(p) => std::path::PathBuf::from(p),
Err(_) => {
eprintln!(
"FALSIFICATION-SKIP: gate=stress_max_tokens_one reason=TEST_MODEL_PATH not set"
);
return;
}
};
let output = std::process::Command::new("cargo")
.args([
"run",
"--bin",
"apr",
"--features",
"inference",
"--",
"run",
&model_path.to_string_lossy(),
"--prompt",
"Hello",
"--max-tokens",
"1",
"--temperature",
"0",
])
.output()
.expect("max_tokens=1 generation");
assert!(
output.status.success(),
"max_tokens=1 must succeed: {}",
String::from_utf8_lossy(&output.stderr)
);
let text = String::from_utf8_lossy(&output.stdout);
assert!(
!text.trim().is_empty(),
"max_tokens=1 must produce at least some output"
);
}
#[test]
fn stress_single_token_prompt() {
let model_path = match std::env::var("TEST_MODEL_PATH") {
Ok(p) => std::path::PathBuf::from(p),
Err(_) => {
eprintln!("FALSIFICATION-SKIP: gate=stress_single_token_prompt reason=TEST_MODEL_PATH not set");
return;
}
};
let output = std::process::Command::new("cargo")
.args([
"run",
"--bin",
"apr",
"--features",
"inference",
"--",
"run",
&model_path.to_string_lossy(),
"--prompt",
"Hi",
"--max-tokens",
"8",
"--temperature",
"0",
])
.output()
.expect("single token prompt generation");
assert!(
output.status.success(),
"Single-token prompt must succeed: {}",
String::from_utf8_lossy(&output.stderr)
);
}
#[test]
fn stress_long_prompt_no_panic() {
let model_path = match std::env::var("TEST_MODEL_PATH") {
Ok(p) => std::path::PathBuf::from(p),
Err(_) => {
eprintln!("FALSIFICATION-SKIP: gate=stress_long_prompt_no_panic reason=TEST_MODEL_PATH not set");
return;
}
};
let long_prompt = "The quick brown fox jumps over the lazy dog. ".repeat(50);
let output = std::process::Command::new("cargo")
.args([
"run",
"--bin",
"apr",
"--features",
"inference",
"--",
"run",
&model_path.to_string_lossy(),
"--prompt",
&long_prompt,
"--max-tokens",
"8",
"--temperature",
"0",
])
.output()
.expect("long prompt generation");
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
!stderr.contains("panicked"),
"Long prompt must not cause panic: {stderr}"
);
}
}
#[test]
fn stress_20_sequential_generations() {
let model_path = match std::env::var("TEST_MODEL_PATH") {
Ok(p) => std::path::PathBuf::from(p),
Err(_) => {
eprintln!("FALSIFICATION-SKIP: gate=stress_20_sequential_generations reason=TEST_MODEL_PATH not set");
return;
}
};
let mut outputs = Vec::new();
for i in 0..20 {
let output = std::process::Command::new("cargo")
.args([
"run",
"--bin",
"apr",
"--features",
"inference",
"--",
"run",
&model_path.to_string_lossy(),
"--prompt",
&format!("The number {} is", i + 1),
"--max-tokens",
"4",
"--temperature",
"0",
])
.output()
.unwrap_or_else(|_| panic!("Generation {i} failed to execute"));
assert!(
output.status.success(),
"Generation {i}/20 must succeed: {}",
String::from_utf8_lossy(&output.stderr)
);
let text = String::from_utf8_lossy(&output.stdout).to_string();
outputs.push(text);
}
let non_empty = outputs.iter().filter(|o| !o.trim().is_empty()).count();
assert!(
non_empty >= 15,
"At least 15/20 generations must produce output (got {non_empty})"
);
}
#[test]
fn stress_serve_health_check() {
let model_path = match std::env::var("TEST_MODEL_PATH") {
Ok(p) => std::path::PathBuf::from(p),
Err(_) => {
eprintln!(
"FALSIFICATION-SKIP: gate=stress_serve_health_check reason=TEST_MODEL_PATH not set"
);
return;
}
};
let mut child = match std::process::Command::new("cargo")
.args([
"run",
"--bin",
"apr",
"--features",
"inference",
"--",
"serve",
&model_path.to_string_lossy(),
"--port",
"18901",
])
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.spawn()
{
Ok(c) => c,
Err(e) => {
eprintln!(
"FALSIFICATION-SKIP: gate=stress_serve_health_check reason=spawn failed: {e}"
);
return;
}
};
std::thread::sleep(std::time::Duration::from_secs(5));
let health = std::process::Command::new("curl")
.args([
"-s",
"-o",
"/dev/null",
"-w",
"%{http_code}",
"http://localhost:18901/health",
])
.output();
let _ = child.kill();
let _ = child.wait();
if let Ok(h) = health {
let code = String::from_utf8_lossy(&h.stdout);
assert!(
code == "200" || code == "404",
"Serve health check returned unexpected code: {code}"
);
}
}
#[test]
fn stress_chat_50_messages() {
let template = aprender::text::chat_template::auto_detect_template("qwen2.5-coder");
let mut messages = Vec::new();
for i in 0..50 {
if i % 2 == 0 {
messages.push(aprender::text::chat_template::ChatMessage::user(format!(
"Question {}: What is {}+{}?",
i / 2 + 1,
i,
i + 1
)));
} else {
messages.push(aprender::text::chat_template::ChatMessage::assistant(
format!("The answer is {}.", i + (i + 1)),
));
}
}
let formatted = template.format_conversation(&messages).expect("format");
assert!(!formatted.is_empty(), "50-message conversation must format");
assert!(
formatted.contains("user") || formatted.contains("im_start"),
"Formatted conversation must contain role markers"
);
}
#[test]
fn stress_chat_large_message() {
let template = aprender::text::chat_template::auto_detect_template("qwen2.5-coder");
let large_content = "x".repeat(100_000);
let messages = vec![aprender::text::chat_template::ChatMessage::user(
large_content,
)];
let formatted = template.format_conversation(&messages).expect("format");
assert!(formatted.len() > 100_000, "Large message must be preserved");
}
#[test]
fn stress_chat_empty_messages() {
let template = aprender::text::chat_template::auto_detect_template("qwen2.5-coder");
let messages = vec![
aprender::text::chat_template::ChatMessage::user(String::new()),
aprender::text::chat_template::ChatMessage::assistant(String::new()),
];
let formatted = template.format_conversation(&messages).expect("format");
assert!(
!formatted.is_empty(),
"Empty messages must still format with template markers"
);
}
#[test]
fn stress_chat_system_only() {
let template = aprender::text::chat_template::auto_detect_template("qwen2.5-coder");
let messages = vec![aprender::text::chat_template::ChatMessage::system(
"You are helpful.".to_string(),
)];
let formatted = template.format_conversation(&messages).expect("format");
assert!(!formatted.is_empty(), "System-only message must format");
}
#[test]
fn stress_alternating_roles_no_panic() {
let template = aprender::text::chat_template::auto_detect_template("qwen2.5-coder");
let roles = ["system", "user", "assistant", "user", "assistant"];
let messages: Vec<_> = roles
.iter()
.enumerate()
.map(|(i, &role)| {
aprender::text::chat_template::ChatMessage::new(
role.to_string(),
format!("Message {i}"),
)
})
.collect();
let formatted = template.format_conversation(&messages).expect("format");
assert!(!formatted.is_empty());
}
#[test]
fn stress_consecutive_user_messages() {
let template = aprender::text::chat_template::auto_detect_template("qwen2.5-coder");
let messages = vec![
aprender::text::chat_template::ChatMessage::user("First question".to_string()),
aprender::text::chat_template::ChatMessage::user("Second question".to_string()),
aprender::text::chat_template::ChatMessage::user("Third question".to_string()),
];
let formatted = template.format_conversation(&messages).expect("format");
assert!(
!formatted.is_empty(),
"Consecutive user messages must format"
);
}