- 夹具误用错误行信号(.rs:)做普通大结果,错误行全量保留致压缩断言先天不成立,改中性行 - 生产行为缺陷(错误行洪泛击穿压缩,grep/rustc 类输出为主要受害者)登记看板待修
86 lines
3.4 KiB
Rust
86 lines
3.4 KiB
Rust
//! P1 工具结果瘦身 — 端到端集成验证。
|
|
//!
|
|
//! 独立测试二进制(独立进程):`tool_offload::init_base` 的 OnceLock 全局态不外泄,
|
|
//! 不污染 lib 单测(反之亦然)。这是验证「超阈值 → 落盘句柄 → 可无损读回」全链的唯一安全方式。
|
|
|
|
use df_ai::context_helpers::{extract_key_info, READ_FILE_OFFLOAD_BYTES};
|
|
use df_ai::tool_offload;
|
|
|
|
fn tmp_base(tag: &str) -> std::path::PathBuf {
|
|
std::env::temp_dir().join(format!("df-ai-ctx-offload-{tag}-{}", std::process::id()))
|
|
}
|
|
|
|
/// 从句柄行里粗取落盘路径(格式:`[...已外置: <path> —— ...]`)。
|
|
fn path_of(handle_line: &str) -> String {
|
|
handle_line
|
|
.split("已外置: ")
|
|
.nth(1)
|
|
.and_then(|s| s.split(" ——").next())
|
|
.expect("句柄行应含路径")
|
|
.trim()
|
|
.to_string()
|
|
}
|
|
|
|
#[test]
|
|
fn large_read_file_summarized_with_lossless_handle() {
|
|
let base = tmp_base("large");
|
|
let _ = std::fs::remove_dir_all(&base);
|
|
tool_offload::init_base(base.clone());
|
|
|
|
// 造一个超阈值的 read_file 结果(代码风格多行文本)
|
|
let body: String = (1..=800)
|
|
.map(|i| format!("line {i}: fn sample_{i}() {{ let x = {i}; }}\n"))
|
|
.collect();
|
|
assert!(body.len() > READ_FILE_OFFLOAD_BYTES, "夹具须超阈值");
|
|
|
|
let out = extract_key_info(&body, "read_file");
|
|
assert!(out.len() < body.len(), "超阈值 read_file 应被压缩");
|
|
assert!(out.contains("已外置"), "应追加落盘句柄:\n{out}");
|
|
assert!(out.contains("read_file 读该路径"), "句柄应指引读回方式");
|
|
|
|
// 无损性:按句柄路径读回 = 原文逐字节一致
|
|
let line = out.lines().find(|l| l.contains("已外置")).expect("应有句柄行");
|
|
let back = tool_offload::read_offloaded(&path_of(line)).expect("句柄路径应可读回");
|
|
assert_eq!(back, body, "落盘原文须与输入逐字节一致(无损)");
|
|
|
|
// 摘要确实变小(瘦身生效)
|
|
let ratio = out.len() as f64 / body.len() as f64;
|
|
assert!(ratio < 0.2, "压缩比应显著(<0.2),实际 {ratio:.3}");
|
|
|
|
let _ = std::fs::remove_dir_all(&base);
|
|
}
|
|
|
|
#[test]
|
|
fn small_read_file_still_exempt() {
|
|
let base = tmp_base("small");
|
|
tool_offload::init_base(base);
|
|
let small = "line1: fn a() {}\nline2: fn b() {}\n";
|
|
assert_eq!(
|
|
extract_key_info(small, "read_file"),
|
|
small,
|
|
"阈值内 read_file 应原样返回(保 AI 定向读代码语义)"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn non_read_file_large_result_also_gets_handle() {
|
|
let base = tmp_base("other");
|
|
let _ = std::fs::remove_dir_all(&base);
|
|
tool_offload::init_base(base.clone());
|
|
|
|
// 中性行夹具:不得含 error/panic/.rs: 等错误行信号——错误行保留策略会全量保留
|
|
// 命中行,用信号行做夹具会让「应被压缩」断言先天不成立(测的是普通大结果外置)
|
|
let body: String = (1..=1200).map(|i| format!("match {i}: src/foo.txt:{i}\n")).collect();
|
|
assert!(body.len() >= 8 * 1024, "夹具须 ≥8KB(句柄追加下限)");
|
|
let out = extract_key_info(&body, "grep");
|
|
assert!(out.len() < body.len(), "应被压缩");
|
|
assert!(out.contains("已外置"), "≥8KB 结果应带落盘句柄");
|
|
|
|
let line = out.lines().find(|l| l.contains("已外置")).expect("应有句柄行");
|
|
assert_eq!(
|
|
tool_offload::read_offloaded(&path_of(line)).expect("应可读回"),
|
|
body
|
|
);
|
|
let _ = std::fs::remove_dir_all(&base);
|
|
}
|