use dbgscope::dbgeng::DebugEngine;
use std::time::Instant;
fn listing(e: &DebugEngine) -> String {
e.execute_command("|").unwrap_or_default()
}
fn count(listing: &str) -> usize {
listing.lines().filter(|l| l.contains("id:")).count()
}
fn how_many_creates_one_pump_realises() {
println!("\n=== A. two queued creates, one explicit wait ===");
let e = DebugEngine::new();
let first = e.launch_process_begin("cmd.exe /c ping -n 30 127.0.0.1");
let second = e.launch_process_begin("ping.exe -n 30 127.0.0.2");
println!(
" both begun: {:?} / {:?}, session {} process(es)",
first.is_ok(),
second.is_ok(),
count(&listing(&e))
);
drop(first);
drop(second);
for pump in 1..=3 {
let started = Instant::now();
let waited = e.wait_for_event(20_000);
println!(
" pump {pump}: {:?} in {:?}, session now {} process(es)",
waited.as_ref().map(|_| "Ok").map_err(|err| err.to_string()),
started.elapsed(),
count(&listing(&e))
);
}
let _ = e.end_session();
}
fn where_a_bad_image_fails() {
println!("\n=== B. launch_process_begin on an image that does not exist ===");
let e = DebugEngine::new();
let started = Instant::now();
let begun = e.launch_process_begin("no_such_program_xyzzy.exe");
println!(
" launch_process_begin -> {:?} in {:?}",
begun
.as_ref()
.map(|_| "Ok(guard)")
.map_err(|e| e.to_string()),
started.elapsed()
);
match begun {
Err(_) => println!(
" => fails AT BEGIN, so a guard for a launch that never starts is not constructible \
and nothing has to retire one."
),
Ok(guard) => {
let waited = guard.wait();
println!(
" guard.wait() -> {:?}",
waited.as_ref().map(|()| "Ok").map_err(|e| e.to_string())
);
println!(" => fails IN THE WAIT, so a kept entry needs something to retire it.");
}
}
let _ = e.end_session();
}
fn does_the_next_launch_get_its_own_process(round: usize) -> bool {
let e = DebugEngine::new();
let first = e.launch_process_begin("cmd.exe /c ping -n 30 127.0.0.1");
drop(first);
let Ok(second) = e.launch_process_begin("ping.exe -n 30 127.0.0.2") else {
println!(" round {round}: the second launch would not begin");
return true;
};
let waited = second.wait();
let text = listing(&e);
let mine = text.contains("ping.exe");
println!(
" round {round}: wait() -> {:?}, {} process(es), own program present: {mine}{}",
waited.as_ref().map(|()| "Ok").map_err(|e| e.to_string()),
count(&text),
if mine { "" } else { " <-- SHORT" }
);
let _ = e.end_session();
mine
}
fn main() {
where_a_bad_image_fails();
how_many_creates_one_pump_realises();
println!("\n=== C. abandon a launch, then launch a different program ===");
println!(" (SHORT = wait() returned before this guard's own process was there)");
let short = (1..=10)
.filter(|round| !does_the_next_launch_get_its_own_process(*round))
.count();
println!(" short in 10: {short}");
}