use std::path::Path;
use std::time::Duration;
use ek_ui::launch::{LaunchFail, launch, spawn_detached, unique_marker, wait_ready};
use ek_ui::pick::{PickErr, read_pick, write_pick_in};
fn tmp_sub(tag: &str) -> std::path::PathBuf {
std::env::temp_dir().join(format!("ek-ui-test-{}-{tag}", std::process::id()))
}
#[test]
fn k0_pick_roundtrip() {
let dir = tmp_sub("k0");
let written = write_pick_in(&dir, &["dm", "oms", "ui"]).unwrap();
let got = read_pick(&written).unwrap();
assert_eq!(
got,
vec!["dm".to_string(), "oms".to_string(), "ui".to_string()]
);
}
#[test]
fn k1_pick_strict_rules() {
let dir = tmp_sub("k1");
std::fs::create_dir_all(&dir).unwrap();
let path = dir.join("bad.list");
std::fs::write(&path, "# 注释行\n dm oms\ndm\n").unwrap();
let err = read_pick(&path).unwrap_err();
assert!(
matches!(err, PickErr::BadLine(2, ref s) if s.contains("dm oms")),
"got {err:?}"
);
let empty = dir.join("empty.list");
std::fs::write(&empty, " \n# 仅注释\n\n").unwrap();
assert_eq!(read_pick(&empty).unwrap_err(), PickErr::Empty);
let werr = write_pick_in(&dir, &["dm oms"]).unwrap_err();
assert!(werr.to_string().contains("whitespace"));
assert_eq!(write_pick_in(&dir, &[]).unwrap_err(), PickErr::Empty);
}
fn ps_cmd(script: &str) -> Vec<String> {
vec![
"-NoProfile".to_string(),
"-Command".to_string(),
script.to_string(),
]
}
#[test]
fn k2_launch_success_ready_marker() {
let dir = tmp_sub("k2");
let marker = unique_marker(&dir);
let script = format!(
"Set-Content -LiteralPath '{}' -Value 'ready'; exit 0",
marker.display()
);
let r = launch(
Path::new("powershell"),
&ps_cmd(&script),
&marker,
Duration::from_secs(20),
);
assert!(r.is_ok(), "expected ok, got {r:?}");
assert!(marker.is_file(), "ready marker must exist");
}
#[test]
fn k3_launch_exit_without_marker() {
let dir = tmp_sub("k3");
let marker = unique_marker(&dir);
let script = "$host.UI.WriteErrorLine('boom'); exit 1";
let r = launch(
Path::new("powershell"),
&ps_cmd(script),
&marker,
Duration::from_secs(20),
);
match r {
Err(LaunchFail::Exited { code, stderr_tail }) => {
assert_eq!(code, 1);
assert!(stderr_tail.contains("boom"), "tail: {stderr_tail:?}");
}
other => panic!("expected Exited(1), got {other:?}"),
}
}
#[test]
fn k4_launch_timeout_notready_and_kill() {
let dir = tmp_sub("k4");
let marker = unique_marker(&dir); let mut child =
spawn_detached(Path::new("powershell"), &ps_cmd("Start-Sleep -Seconds 8")).unwrap();
let short = Duration::from_millis(700);
let r = wait_ready(&mut child, &marker, short);
match r {
Err(LaunchFail::NoReadySignal { timeout }) => assert_eq!(timeout, short),
other => panic!("expected NoReadySignal, got {other:?}"),
}
let _ = child.kill();
}