aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2021-03-13 01:52:21 -0500
committerJesse Luehrs <doy@tozt.net>2021-03-13 01:52:21 -0500
commit8dfc9648c161e11a0cebd22e44452413cf3f8788 (patch)
treeb3cb5215304c11b4c8bf6a2fd52377abb6d6444f
parent1aa54fb6b45e8eea4604f8c8acaecb3bb9086fb4 (diff)
downloadtextmode-8dfc9648c161e11a0cebd22e44452413cf3f8788.tar.gz
textmode-8dfc9648c161e11a0cebd22e44452413cf3f8788.zip
refactor, start working on input test
-rw-r--r--tests/basic.rs7
l---------tests/fixtures/bin/src/bin/input.rs1
-rw-r--r--tests/fixtures/mod.rs135
-rw-r--r--tests/input.rs247
4 files changed, 353 insertions, 37 deletions
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<F>(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<F: FnOnce(&mut std::fs::File)>(
+ &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<u8> {
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<u8> {
buf
}
+#[allow(dead_code)]
+pub fn read_line(f: &mut std::io::BufReader<&mut std::fs::File>) -> Vec<u8> {
+ 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());
+ });
+}