use std::path::Path;
use std::sync::Mutex;
mod common;
use common::{copy_dir, openai_compatible_config, unique_dir};
#[test]
fn test_pipeline_progress_events_monotonic_and_done() {
let fixture = Path::new(env!("CARGO_MANIFEST_DIR"))
.join("tests")
.join("fixtures")
.join("sample-repo");
let work_dir = unique_dir("progress_repo");
let _ = std::fs::remove_dir_all(&work_dir);
copy_dir(&fixture, &work_dir);
let root = code_repo_wiki::project::ProjectRoot::new(work_dir.clone());
let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
let port = listener.local_addr().unwrap().port();
std::thread::spawn(move || {
use std::io::{Read, Write};
for stream in listener.incoming() {
let mut s = match stream {
Ok(s) => s,
Err(_) => continue,
};
let mut buf = [0u8; 4096];
let _ = s.read(&mut buf);
let body = br#"{"choices":[{"message":{"content":"mock"}}]}"#;
let head = format!(
"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: {}\r\nConnection: close\r\n\r\n",
body.len()
);
let _ = s.write_all(head.as_bytes());
let _ = s.write_all(body);
}
});
let config = openai_compatible_config(port);
std::fs::write(work_dir.join("mock-server.toml"), config).unwrap();
let events: Mutex<Vec<code_repo_wiki::ProgressEvent>> = Mutex::new(Vec::new());
let result = code_repo_wiki::run_pipeline_with_progress(
Some(&work_dir.join("mock-server.toml")),
None,
true,
&root,
&code_repo_wiki::GenerationMode::Full,
&|evt| events.lock().unwrap().push(evt),
);
assert!(result.is_ok(), "流水线应成功(LLM 失败被容错跳过): {:?}", result.err());
let events = events.into_inner().unwrap();
assert!(!events.is_empty(), "应收到进度事件");
assert_eq!(events.first().unwrap().stage, "scanning");
for w in events.windows(2) {
assert!(
w[1].percent >= w[0].percent,
"事件百分比应单调递增: {} ({}%) -> {} ({}%)",
w[0].stage, w[0].percent, w[1].stage, w[1].percent
);
}
assert_eq!(events.last().unwrap().stage, "done");
assert_eq!(events.last().unwrap().percent, 100);
let _ = std::fs::remove_dir_all(&work_dir);
}