From 8dfc9648c161e11a0cebd22e44452413cf3f8788 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Sat, 13 Mar 2021 01:52:21 -0500 Subject: refactor, start working on input test --- tests/basic.rs | 7 +- tests/fixtures/bin/src/bin/input.rs | 1 + tests/fixtures/mod.rs | 135 +++++++++++++++----- tests/input.rs | 247 ++++++++++++++++++++++++++++++++++++ 4 files changed, 353 insertions(+), 37 deletions(-) create mode 120000 tests/fixtures/bin/src/bin/input.rs create mode 100644 tests/input.rs diff --git a/tests/basic.rs b/tests/basic.rs index 3b52bc2..c18477b 100644 --- a/tests/basic.rs +++ b/tests/basic.rs @@ -5,7 +5,8 @@ mod fixtures; #[test] fn test_basic() { - fixtures::run_fixture("basic", "", true, |pty| { + let fixture = fixtures::Fixture::new("basic"); + fixture.build().run(&[], |pty| { pty.write_all(b"a").unwrap(); assert_eq!(fixtures::read(pty), b"\x1b[6;6Hfoo"); @@ -24,7 +25,9 @@ fn test_basic() { #[test] fn test_async() { - fixtures::run_fixture("async", "async", true, |pty| { + let mut fixture = fixtures::Fixture::new("async"); + fixture.features("async"); + fixture.build().run(&[], |pty| { pty.write_all(b"a").unwrap(); assert_eq!(fixtures::read(pty), b"\x1b[6;6Hfoo"); diff --git a/tests/fixtures/bin/src/bin/input.rs b/tests/fixtures/bin/src/bin/input.rs new file mode 120000 index 0000000..3347dbb --- /dev/null +++ b/tests/fixtures/bin/src/bin/input.rs @@ -0,0 +1 @@ +../../../../../examples/input.rs \ No newline at end of file diff --git a/tests/fixtures/mod.rs b/tests/fixtures/mod.rs index 61d9e04..ef5a742 100644 --- a/tests/fixtures/mod.rs +++ b/tests/fixtures/mod.rs @@ -1,48 +1,104 @@ use pty_process::Command as _; -use std::io::Read as _; +use std::io::{BufRead as _, Read as _}; use std::os::unix::io::AsRawFd as _; -pub fn run_fixture(name: &str, features: &str, screenguard: bool, f: F) -where - F: FnOnce(&mut std::fs::File), -{ - let temp = assert_fs::TempDir::new().unwrap(); - let run = escargot::CargoBuild::new() - .bin(name) - .current_release() - .current_target() - .manifest_path("tests/fixtures/bin/Cargo.toml") - .target_dir(temp.path()) - .features(features) - .run() - .unwrap(); - let mut cmd = run.command(); - let mut child = cmd - .spawn_pty(Some(&pty_process::Size::new(24, 80))) - .unwrap(); - - if screenguard { - assert!(read_ready(child.pty().as_raw_fd())); - let mut buf = vec![0u8; 1024]; - let bytes = child.pty().read(&mut buf).unwrap(); - buf.truncate(bytes); - assert_eq!(&buf[..], b"\x1b7\x1b[?47h\x1b[2J\x1b[H\x1b[?25h"); +pub struct Fixture { + name: String, + features: String, + screenguard: bool, + + tempdir: assert_fs::TempDir, +} + +impl Fixture { + pub fn new(name: &str) -> Self { + Self { + name: name.to_string(), + features: String::new(), + screenguard: true, + tempdir: assert_fs::TempDir::new().unwrap(), + } + } + + #[allow(dead_code)] + pub fn features(&mut self, features: &str) { + self.features = features.to_string(); } - f(child.pty_mut()); + #[allow(dead_code)] + pub fn screenguard(&mut self, screenguard: bool) { + self.screenguard = screenguard; + } + + pub fn build(self) -> BuiltFixture { + let Self { + name, + features, + screenguard, + tempdir, + } = self; + let run = escargot::CargoBuild::new() + .bin(name) + .current_release() + .current_target() + .manifest_path("tests/fixtures/bin/Cargo.toml") + .target_dir(tempdir.path()) + .features(features) + .run() + .unwrap(); - if screenguard { - assert!(read_ready(child.pty().as_raw_fd())); - let mut buf = vec![0u8; 1024]; - let bytes = child.pty().read(&mut buf).unwrap(); - buf.truncate(bytes); - assert_eq!(&buf[..], b"\x1b[?47l\x1b8\x1b[?25h"); + BuiltFixture { + _tempdir: tempdir, + run, + screenguard, + } } +} - let status = child.wait().unwrap(); - assert!(status.success()); +pub struct BuiltFixture { + _tempdir: assert_fs::TempDir, + run: escargot::CargoRun, + screenguard: bool, } +impl BuiltFixture { + pub fn run( + &mut self, + args: &[&str], + f: F, + ) { + let mut cmd = self.run.command(); + let mut child = cmd + .args(args) + .spawn_pty(Some(&pty_process::Size::new(24, 80))) + .unwrap(); + + if self.screenguard { + assert!(read_ready(child.pty().as_raw_fd())); + let mut buf = vec![0u8; 1024]; + let bytes = child.pty().read(&mut buf).unwrap(); + buf.truncate(bytes); + assert_eq!(&buf[..], b"\x1b7\x1b[?47h\x1b[2J\x1b[H\x1b[?25h"); + } else { + std::thread::sleep(std::time::Duration::from_millis(100)); + } + + f(child.pty_mut()); + + if self.screenguard { + assert!(read_ready(child.pty().as_raw_fd())); + let mut buf = vec![0u8; 1024]; + let bytes = child.pty().read(&mut buf).unwrap(); + buf.truncate(bytes); + assert_eq!(&buf[..], b"\x1b[?47l\x1b8\x1b[?25h"); + } + + let status = child.wait().unwrap(); + assert!(status.success()); + } +} + +#[allow(dead_code)] pub fn read(f: &mut std::fs::File) -> Vec { assert!(read_ready(f.as_raw_fd())); let mut buf = vec![0u8; 1024]; @@ -51,6 +107,15 @@ pub fn read(f: &mut std::fs::File) -> Vec { buf } +#[allow(dead_code)] +pub fn read_line(f: &mut std::io::BufReader<&mut std::fs::File>) -> Vec { + assert!(!f.buffer().is_empty() || read_ready(f.get_ref().as_raw_fd())); + let mut buf = vec![]; + f.read_until(b'\n', &mut buf).unwrap(); + buf +} + +#[allow(dead_code)] pub fn read_ready(fd: std::os::unix::io::RawFd) -> bool { let mut set = nix::sys::select::FdSet::new(); set.insert(fd); diff --git a/tests/input.rs b/tests/input.rs new file mode 100644 index 0000000..79aaea7 --- /dev/null +++ b/tests/input.rs @@ -0,0 +1,247 @@ +#![allow(clippy::collapsible_if)] + +use std::io::Write as _; +use std::os::unix::io::AsRawFd as _; + +mod fixtures; + +#[test] +fn test_basic() { + let mut fixture = fixtures::Fixture::new("input"); + fixture.screenguard(false); + let mut run = fixture.build(); + + for utf8 in &[true, false] { + for ctrl in &[true, false] { + for meta in &[true, false] { + for special_keys in &[true, false] { + for single in &[true, false] { + run_input_test( + &mut run, + *utf8, + *ctrl, + *meta, + *special_keys, + *single, + ); + } + } + } + } + } +} + +#[test] +fn test_async() { + let mut fixture = fixtures::Fixture::new("input"); + fixture.screenguard(false); + fixture.features("async"); + let mut run = fixture.build(); + + for utf8 in &[true, false] { + for ctrl in &[true, false] { + for meta in &[true, false] { + for special_keys in &[true, false] { + for single in &[true, false] { + run_input_test( + &mut run, + *utf8, + *ctrl, + *meta, + *special_keys, + *single, + ); + } + } + } + } + } +} + +fn run_input_test( + fixture: &mut fixtures::BuiltFixture, + utf8: bool, + ctrl: bool, + meta: bool, + special_keys: bool, + single: bool, +) { + let mut args = vec![]; + if !utf8 { + args.push("--disable-utf8") + } + if !ctrl { + args.push("--disable-ctrl") + } + if !meta { + args.push("--disable-meta") + } + if !special_keys { + args.push("--disable-special-keys") + } + if !single { + args.push("--disable-single") + } + + fixture.run(&args, |pty| { + let mut r = std::io::BufReader::new(pty); + + r.get_mut() + .write_all(&textmode::Key::Up.into_bytes()) + .unwrap(); + if special_keys { + assert_eq!( + std::string::String::from_utf8(fixtures::read_line(&mut r)) + .unwrap(), + "Up: [27, 91, 65]\r\n" + ); + } else { + if single { + if utf8 { + assert_eq!( + std::string::String::from_utf8(fixtures::read_line( + &mut r + )) + .unwrap(), + "Byte(27): [27]\r\n" + ); + assert_eq!( + std::string::String::from_utf8(fixtures::read_line( + &mut r + )) + .unwrap(), + "Char('['): [91]\r\n" + ); + assert_eq!( + std::string::String::from_utf8(fixtures::read_line( + &mut r + )) + .unwrap(), + "Char('A'): [65]\r\n" + ); + } else { + assert_eq!( + std::string::String::from_utf8(fixtures::read_line( + &mut r + )) + .unwrap(), + "Byte(27): [27]\r\n" + ); + assert_eq!( + std::string::String::from_utf8(fixtures::read_line( + &mut r + )) + .unwrap(), + "Byte(91): [91]\r\n" + ); + assert_eq!( + std::string::String::from_utf8(fixtures::read_line( + &mut r + )) + .unwrap(), + "Byte(65): [65]\r\n" + ); + } + } else { + if utf8 { + // assert_eq!( + // std::string::String::from_utf8(fixtures::read_line( + // &mut r + // )) + // .unwrap(), + // "Bytes([27]): [27]\r\n" + // ); + // assert_eq!( + // std::string::String::from_utf8(fixtures::read_line( + // &mut r + // )) + // .unwrap(), + // "String(\"[A\"): [91, 65]\r\n" + // ); + if meta { + assert_eq!( + std::string::String::from_utf8( + fixtures::read_line(&mut r) + ) + .unwrap(), + "Bytes([27]): [27]\r\n" + ); + assert_eq!( + std::string::String::from_utf8( + fixtures::read_line(&mut r) + ) + .unwrap(), + "String(\"[A\"): [91, 65]\r\n" + ); + } else { + assert_eq!( + std::string::String::from_utf8( + fixtures::read_line(&mut r) + ) + .unwrap(), + "Bytes([27, 91, 65]): [27, 91, 65]\r\n" + ); + } + } else { + if meta { + assert_eq!( + std::string::String::from_utf8( + fixtures::read_line(&mut r) + ) + .unwrap(), + "Bytes([27]): [27]\r\n" + ); + assert_eq!( + std::string::String::from_utf8( + fixtures::read_line(&mut r) + ) + .unwrap(), + "Bytes([91, 65]): [91, 65]\r\n" + ); + } else { + assert_eq!( + std::string::String::from_utf8( + fixtures::read_line(&mut r) + ) + .unwrap(), + "Bytes([27, 91, 65]): [27, 91, 65]\r\n" + ); + } + } + } + } + assert!(!fixtures::read_ready(r.get_ref().as_raw_fd())); + assert!(r.buffer().is_empty()); + + r.get_mut() + .write_all(&textmode::Key::Ctrl(b'c').into_bytes()) + .unwrap(); + if ctrl { + assert_eq!( + std::string::String::from_utf8(fixtures::read_line(&mut r)) + .unwrap(), + "Ctrl(99): [3]\r\n" + ); + } else { + if single { + assert_eq!( + std::string::String::from_utf8(fixtures::read_line( + &mut r + )) + .unwrap(), + "Byte(3): [3]\r\n" + ); + } else { + assert_eq!( + std::string::String::from_utf8(fixtures::read_line( + &mut r + )) + .unwrap(), + "Bytes([3]): [3]\r\n" + ); + } + } + assert!(!fixtures::read_ready(r.get_ref().as_raw_fd())); + assert!(r.buffer().is_empty()); + }); +} -- cgit v1.2.3-54-g00ecf