T23: the shell tests type a line only once the line editor reads raw keys: on CI's pwsh 7.6.6 the probe, typed right after the first folder report, came before PSReadLine's first read and was echoed, never run; shot warns when the app it runs under lacks Screen Recording, which left this Mac's pictures with the window's ground alone; AGENTS.md records the CI runners, the build without debuginfo and the typing rule
CI / platforms (ubuntu-24.04) (push) Successful in 1m14s
CI / platforms (windows-latest) (push) Successful in 2m23s
CI / macos (push) Successful in 10m26s

This commit is contained in:
ZacharyZhang-NY committed 2026-10-15 13:50:09 -04:00
1 parent de48f491bc
commit be8d0e20c5
5 files changed
+37 -4

No files matched your search

+18
View File
@@ -56,6 +56,8 @@ pub struct Pty {
pub term: Arc<FairMutex<Term<Listener>>>,
pub pid: u32,
notifier: Notifier,
#[cfg(all(test, unix))]
master: std::fs::File,
}
/// What a pty reports, in order.
@@ -109,6 +111,10 @@ pub fn spawn(
)
})?;
let pid = child_id(&raw)?;
#[cfg(all(test, unix))]
let master = raw
.master()
.map_err(|error| anyhow::anyhow!("pty {pid}: no copy of the master: {error}"))?;
log::info!(
"pty {pid}: started {:?} in {}",
launch.program,
@@ -135,6 +141,8 @@ pub fn spawn(
term,
pid,
notifier,
#[cfg(all(test, unix))]
master,
},
events,
))
@@ -176,6 +184,16 @@ impl Pty {
}
}
#[cfg(all(test, unix))]
impl Pty {
/// Whether the program reads keys one by one, as a line editor does.
pub(crate) fn reads_keys(&self) -> bool {
use rustix_openpty::rustix::termios::{LocalModes, tcgetattr};
let modes = tcgetattr(&self.master).expect("the pty's modes");
!modes.local_modes.contains(LocalModes::ICANON)
}
}
impl Drop for Pty {
fn drop(&mut self) {
if self.notifier.0.send(Msg::Shutdown).is_err() {
+4 -2
View File
@@ -108,7 +108,9 @@ impl Run {
}
}
fn send(&self, line: &str) {
/// Types `line` at a prompt, once its line editor reads raw keys.
fn send(&mut self, line: &str) {
self.until("line editor", |run| run.pty.reads_keys());
self.pty.write(format!("{line}\r").into_bytes());
}
@@ -131,9 +133,9 @@ impl Run {
/// The prompt's folder, the script loaded by `probe`, then a cd into the inner folder.
fn walk(&mut self, probe: &str) {
let start = self.start.clone();
self.send(probe);
self.until("first folder", |run| run.folders.contains(&start));
assert_eq!(self.folders[0], start);
self.send(probe);
self.until("loaded script", |run| run.shows("ELY-LOADED"));
self.send("cd in*");
let inner = start.join(INNER);
+6
View File
@@ -44,6 +44,12 @@ impl Pty {
pub fn id(&self) -> u32 {
self.child.id()
}
/// A copy of the master, for tests to read its modes.
#[cfg(test)]
pub fn master(&self) -> io::Result<File> {
self.file.try_clone()
}
}
/// Starts `program`, or the login shell, in `cwd` on a new pty of `size`.