summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock1
-rw-r--r--Cargo.toml1
-rw-r--r--tests/integration_tests.rs53
3 files changed, 55 insertions, 0 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 060c41e0..9d34c3c4 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -117,6 +117,7 @@ dependencies = [
"syntect",
"tempdir",
"unicode-width",
+ "wait-timeout",
"wild",
]
diff --git a/Cargo.toml b/Cargo.toml
index 50d7df94..212db77a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -76,6 +76,7 @@ default-features = false
tempdir = "0.3"
assert_cmd = "1.0.2"
predicates = "1.0.6"
+wait-timeout = "0.2.0"
[build-dependencies]
clap = { version = "2.33", optional = true }
diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs
index 3f125aa1..e16a8a91 100644
--- a/tests/integration_tests.rs
+++ b/tests/integration_tests.rs
@@ -5,8 +5,11 @@ use std::fs::File;
use std::path::Path;
use std::process::{Command, Stdio};
use std::str::from_utf8;
+use std::time::Duration;
const EXAMPLES_DIR: &str = "tests/examples";
+const SAFE_CHILD_PROCESS_CREATION_TIME: Duration = Duration::from_millis(100);
+const CHILD_WAIT_TIMEOUT: Duration = Duration::from_secs(15);
fn bat_raw_command() -> Command {
let mut cmd = Command::cargo_bin("bat").unwrap();
@@ -220,6 +223,56 @@ fn stdin_to_stdout_cycle() {
.failure();
}
+#[cfg(unix)]
+#[test]
+fn no_args_doesnt_break() {
+ use std::io::Write;
+ use std::os::unix::io::FromRawFd;
+ use std::thread;
+
+ use clircle::nix::pty::{openpty, OpenptyResult};
+ use wait_timeout::ChildExt;
+
+ // To simulate bat getting started from the shell, a process is created with stdin and stdout
+ // as the slave end of a pseudo terminal. Although both point to the same "file", bat should
+ // not exit, because in this case it is safe to read and write to the same fd, which is why
+ // this test exists.
+ let OpenptyResult { master, slave } = openpty(None, None).expect("Couldn't open pty.");
+ let mut master = unsafe { File::from_raw_fd(master) };
+ let stdin = unsafe { Stdio::from_raw_fd(slave) };
+ let stdout = unsafe { Stdio::from_raw_fd(slave) };
+
+ let mut child = bat_raw_command()
+ .stdin(stdin)
+ .stdout(stdout)
+ .spawn()
+ .expect("Failed to start.");
+
+ // Some time for the child process to start and to make sure, that we can poll the exit status.
+ // Although this waiting period is not necessary, it is best to keep it in and be absolutely
+ // sure, that the try_wait does not error later.
+ thread::sleep(SAFE_CHILD_PROCESS_CREATION_TIME);
+
+ // The child process should be running and waiting for input,
+ // therefore no exit status should be available.
+ let exit_status = child
+ .try_wait()
+ .expect("Error polling exit status, this should never happen.");
+ assert!(exit_status.is_none());
+
+ // Write Ctrl-D (end of transmission) to the pty.
+ master
+ .write_all(&[0x04])
+ .expect("Couldn't write EOT character to master end.");
+
+ let exit_status = child
+ .wait_timeout(CHILD_WAIT_TIMEOUT)
+ .expect("Error polling exit status, this should never happen.")
+ .expect("Exit status not set, but the child should have exited already.");
+
+ assert!(exit_status.success());
+}
+
#[test]
fn tabs_numbers() {
bat()