use super::{classify_idle_screen, trust_yes_selected, waiting_on_named_windows, IdleScreen};
#[test]
fn trust_dialog_is_not_a_ready_prompt() {
let screen = r#"
Accessing workspace:
Quick safety check
❯ No, exit
Yes, I trust this folder
Enter to confirm
"#;
assert_eq!(classify_idle_screen(screen), IdleScreen::Trust);
}
#[test]
fn trust_yes_requires_the_pointer_on_yes() {
let no = r#"
Accessing workspace:
Yes, I trust this folder
❯ No, exit
Do you trust this folder?
"#;
assert!(!trust_yes_selected(no));
let yes = r#"
Accessing workspace:
❯ Yes, I trust this folder
No, exit
Do you trust this folder?
"#;
assert!(trust_yes_selected(yes));
}
#[test]
fn waits_while_named_fable_header_has_no_percent() {
let partial =
super::super::usage_parse::parse_usage_screen("Current session\n0%used\nResets in 1h\n", 0);
assert!(waiting_on_named_windows(
"Current session\n0%used\nCurrent week (Fable)\n",
partial.as_ref()
));
let complete = super::super::usage_parse::parse_usage_screen(
"Current session\n0%used\nResets in 1h\nCurrent week (Fable)\n33%used\nResets in 2d\n",
0,
);
assert!(!waiting_on_named_windows(
"Current session\n0%used\nCurrent week (Fable)\n33%used\n",
complete.as_ref()
));
}
#[cfg(unix)]
mod pty {
use std::{path::Path, sync::atomic::AtomicBool};
use pretty_assertions::assert_eq;
use super::super::read_usage_from_binary;
fn run_cmd(binary: &str, args: &[&str]) -> super::super::RateLimitState {
run_cmd_grow(binary, args, std::time::Duration::from_millis(400))
}
fn run_cmd_grow(
binary: &str,
args: &[&str],
grow: std::time::Duration,
) -> super::super::RateLimitState {
let env = vec![("TERM".into(), "xterm-256color".into())];
let cwd = tempfile::TempDir::new().unwrap();
read_usage_from_binary(
Path::new(binary),
args,
&env,
cwd.path(),
&AtomicBool::new(false),
grow,
)
.expect("fake /usage")
}
fn assert_session_and_week(state: &super::super::RateLimitState) {
let keys: Vec<&str> = state
.sorted_windows()
.into_iter()
.map(|window| window.info.window_key())
.collect();
assert_eq!(keys, vec!["five_hour", "seven_day"]);
assert_eq!(state.sorted_windows()[0].info.utilization, Some(0.10));
assert_eq!(state.sorted_windows()[1].info.utilization, Some(0.20));
}
#[test]
fn fake_child_usage_panel_parses() {
let script = r#"
printf '? for shortcuts\n❯ '
buf=
while IFS= read -r -n1 c; do
buf="${buf}${c}"
case "$buf" in
*/usage*) break ;;
esac
done
printf '\nCurrent session\n10%% used\nResets in 1h\nCurrent week (all models)\n20%% used\nResets in 2d\n'
exec cat >/dev/null
"#;
assert_session_and_week(&run_cmd("/bin/bash", &["-c", script]));
}
#[test]
fn fake_child_trust_dialog_needs_split_down_and_enter() {
let script = r#"
import os, select, sys, tty
def burst(wait):
fd = sys.stdin.fileno()
if not select.select([fd], [], [], wait)[0]:
return b""
data = os.read(fd, 256)
while select.select([fd], [], [], 0)[0]:
chunk = os.read(fd, 256)
if not chunk:
break
data += chunk
return data
def write(text):
sys.stdout.write(text)
sys.stdout.flush()
tty.setraw(sys.stdin.fileno())
write("Accessing workspace:\nYes, I trust this folder\n❯ No, exit\nDo you trust this folder?\n")
if burst(5.0) != b"\x1b[B":
sys.exit(1)
write("\033[2J\033[HAccessing workspace:\n❯ Yes, I trust this folder\nNo, exit\nDo you trust this folder?\n")
if burst(5.0) != b"\r":
sys.exit(1)
write("\033[2J\033[H? for shortcuts\n❯ Try \"hi\"\nauto mode on (shift+tab to cycle)\n")
buf = b""
while b"/usage" not in buf:
chunk = burst(5.0)
if not chunk:
sys.exit(1)
buf += chunk
write("\nCurrent session\n10% used\nResets in 1h\nCurrent week (all models)\n20% used\nResets in 2d\n")
while os.read(sys.stdin.fileno(), 1024):
pass
"#;
assert_session_and_week(&run_cmd("/usr/bin/python3", &["-c", script]));
}
#[test]
fn fake_child_grow_picks_up_late_fable() {
let cwd = tempfile::TempDir::new().unwrap();
let ready = cwd.path().join("ready");
let go = cwd.path().join("go");
let script = format!(
r#"
printf '? for shortcuts\n❯ '
buf=
while IFS= read -r -n1 c; do
buf="${{buf}}${{c}}"
case "$buf" in
*/usage*) break ;;
esac
done
printf '\nCurrent session\n10%% used\nResets in 1h\nCurrent week (all models)\n20%% used\nResets in 2d\nCurrent week (Fable)\n'
touch {ready}
while [ ! -f {go} ]; do sleep 0.01; done
printf '\nCurrent session\n10%% used\nResets in 1h\nCurrent week (all models)\n20%% used\nResets in 2d\nCurrent week (Fable)\n33%% used\nResets in 2d\n'
exec cat >/dev/null
"#,
ready = ready.display(),
go = go.display()
);
let env = vec![("TERM".into(), "xterm-256color".into())];
let cwd_path = cwd.path().to_path_buf();
let worker = std::thread::spawn(move || {
read_usage_from_binary(
Path::new("/bin/bash"),
&["-c", &script],
&env,
&cwd_path,
&AtomicBool::new(false),
std::time::Duration::from_secs(2),
)
});
let started = std::time::Instant::now();
while !ready.exists() {
assert!(
started.elapsed() < std::time::Duration::from_secs(5),
"child never painted the incomplete panel"
);
std::thread::sleep(std::time::Duration::from_millis(10));
}
std::fs::write(&go, b"").unwrap();
let state = worker.join().expect("probe thread").expect("fake /usage");
let keys: Vec<&str> = state
.sorted_windows()
.into_iter()
.map(|window| window.info.window_key())
.collect();
assert_eq!(keys, vec!["five_hour", "seven_day", "seven_day_fable"]);
assert_eq!(state.sorted_windows()[2].info.utilization, Some(0.33));
}
#[test]
fn abort_flag_stops_a_hung_child() {
use std::sync::atomic::Ordering;
use std::time::{Duration, Instant};
let abort = std::sync::Arc::new(AtomicBool::new(false));
let abort_for_thread = abort.clone();
let started = Instant::now();
let worker = std::thread::spawn(move || {
let env = vec![("TERM".into(), "xterm-256color".into())];
let cwd = tempfile::TempDir::new().unwrap();
super::super::read_usage_from_binary(
Path::new("/bin/sleep"),
&["30"],
&env,
cwd.path(),
abort_for_thread.as_ref(),
Duration::from_secs(2),
)
});
std::thread::sleep(Duration::from_millis(80));
abort.store(true, Ordering::Relaxed);
let result = worker.join().expect("probe thread");
let elapsed = started.elapsed();
assert!(elapsed < Duration::from_secs(5), "{elapsed:?}");
assert!(
matches!(result, Err(super::super::UsageProbeError::Cancelled)),
"{result:?}"
);
}
}