summaryrefslogtreecommitdiffstats
path: root/vendor/xshell/tests
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
commit698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch)
tree173a775858bd501c378080a10dca74132f05bc50 /vendor/xshell/tests
parentInitial commit. (diff)
downloadrustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz
rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/xshell/tests')
-rw-r--r--vendor/xshell/tests/compile_time.rs41
-rw-r--r--vendor/xshell/tests/data/xecho.rs85
-rw-r--r--vendor/xshell/tests/it/compile_failures.rs128
-rw-r--r--vendor/xshell/tests/it/env.rs130
-rw-r--r--vendor/xshell/tests/it/main.rs462
-rw-r--r--vendor/xshell/tests/it/tidy.rs37
6 files changed, 883 insertions, 0 deletions
diff --git a/vendor/xshell/tests/compile_time.rs b/vendor/xshell/tests/compile_time.rs
new file mode 100644
index 000000000..ca35eefe8
--- /dev/null
+++ b/vendor/xshell/tests/compile_time.rs
@@ -0,0 +1,41 @@
+use std::time::{Duration, Instant};
+
+use xshell::{cmd, Shell};
+
+#[test]
+fn fixed_cost_compile_times() {
+ let sh = Shell::new().unwrap();
+
+ let _p = sh.push_dir("tests/data");
+ let baseline = compile_bench(&sh, "baseline");
+ let _ducted = compile_bench(&sh, "ducted");
+ let xshelled = compile_bench(&sh, "xshelled");
+ let ratio = (xshelled.as_millis() as f64) / (baseline.as_millis() as f64);
+ assert!(1.0 < ratio && ratio < 10.0);
+
+ fn compile_bench(sh: &Shell, name: &str) -> Duration {
+ let _p = sh.push_dir(name);
+ let cargo_build = cmd!(sh, "cargo build -q");
+ cargo_build.read().unwrap();
+
+ let n = 5;
+ let mut times = Vec::new();
+ for _ in 0..n {
+ sh.remove_path("./target").unwrap();
+ let start = Instant::now();
+ cargo_build.read().unwrap();
+ let elapsed = start.elapsed();
+ times.push(elapsed);
+ }
+
+ times.sort();
+ times.remove(0);
+ times.pop();
+ let total = times.iter().sum::<Duration>();
+ let average = total / (times.len() as u32);
+
+ eprintln!("compiling {name}: {average:?}");
+
+ total
+ }
+}
diff --git a/vendor/xshell/tests/data/xecho.rs b/vendor/xshell/tests/data/xecho.rs
new file mode 100644
index 000000000..ac86433c3
--- /dev/null
+++ b/vendor/xshell/tests/data/xecho.rs
@@ -0,0 +1,85 @@
+use std::io::{self, Write};
+
+fn main() {
+ if let Err(err) = try_main() {
+ eprintln!("{err}");
+ std::process::exit(1);
+ }
+}
+
+fn try_main() -> io::Result<()> {
+ let mut tee_stderr = false;
+ let mut echo_stdin = false;
+ let mut echo_env = false;
+ let mut fail = false;
+ let mut suicide = false;
+
+ let mut args = std::env::args().skip(1).peekable();
+ while let Some(arg) = args.peek() {
+ match arg.as_str() {
+ "-e" => tee_stderr = true,
+ "-i" => echo_stdin = true,
+ "-$" => echo_env = true,
+ "-f" => fail = true,
+ "-s" => suicide = true,
+ _ => break,
+ }
+ args.next();
+ }
+
+ let stdin = io::stdin();
+ let stdout = io::stdout();
+ let stderr = io::stderr();
+ let mut stdin = stdin.lock();
+ let mut stdout = stdout.lock();
+ let mut stderr = stderr.lock();
+ macro_rules! w {
+ ($($tt:tt)*) => {
+ write!(stdout, $($tt)*)?;
+ if tee_stderr {
+ write!(stderr, $($tt)*)?;
+ }
+ }
+ }
+
+ if echo_stdin {
+ io::copy(&mut stdin, &mut stdout)?;
+ } else if echo_env {
+ for key in args {
+ if let Some(v) = std::env::var_os(&key) {
+ w!("{}={}\n", key, v.to_string_lossy());
+ }
+ }
+ } else {
+ let mut space = "";
+ for arg in args {
+ w!("{}{}", space, arg);
+ space = " ";
+ }
+ w!("\n");
+ }
+
+ if fail {
+ return Err(io::ErrorKind::Other.into());
+ }
+ if suicide {
+ #[cfg(unix)]
+ unsafe {
+ let pid = signals::getpid();
+ if pid > 0 {
+ signals::kill(pid, 9);
+ }
+ }
+ }
+
+ Ok(())
+}
+
+#[cfg(unix)]
+mod signals {
+ use std::os::raw::c_int;
+ extern "C" {
+ pub fn kill(pid: c_int, sig: c_int) -> c_int;
+ pub fn getpid() -> c_int;
+ }
+}
diff --git a/vendor/xshell/tests/it/compile_failures.rs b/vendor/xshell/tests/it/compile_failures.rs
new file mode 100644
index 000000000..611af5acb
--- /dev/null
+++ b/vendor/xshell/tests/it/compile_failures.rs
@@ -0,0 +1,128 @@
+use xshell::{cmd, Shell};
+
+#[track_caller]
+fn check(code: &str, err_msg: &str) {
+ let sh = Shell::new().unwrap();
+ let xshell_dir = sh.current_dir();
+ let temp_dir = sh.create_temp_dir().unwrap();
+ sh.change_dir(temp_dir.path());
+
+ let manifest = format!(
+ r#"
+[package]
+name = "cftest"
+version = "0.0.0"
+edition = "2018"
+[workspace]
+
+[lib]
+path = "main.rs"
+
+[dependencies]
+xshell = {{ path = {xshell_dir:?} }}
+"#,
+ );
+
+ let snip = format!(
+ "
+use xshell::*;
+pub fn f() {{
+ let sh = Shell::new().unwrap();
+ {code};
+}}
+"
+ );
+
+ sh.write_file("Cargo.toml", manifest).unwrap();
+ sh.write_file("main.rs", snip).unwrap();
+
+ let stderr = cmd!(sh, "cargo build").ignore_status().read_stderr().unwrap();
+ assert!(
+ stderr.contains(err_msg),
+ "\n\nCompile fail fail!\n\nExpected:\n{}\n\nActual:\n{}\n",
+ err_msg,
+ stderr
+ );
+}
+
+#[test]
+fn not_a_string_literal() {
+ check("cmd!(sh, 92)", "expected a plain string literal");
+}
+
+#[test]
+fn not_raw_string_literal() {
+ check(r#"cmd!(sh, r"raw")"#, "expected a plain string literal");
+}
+
+#[test]
+fn interpolate_complex_expression() {
+ check(
+ r#"cmd!(sh, "{echo.as_str()}")"#,
+ "error: can only interpolate simple variables, got this expression instead: `echo.as_str()`",
+ );
+}
+
+#[test]
+fn interpolate_splat_concat_prefix() {
+ check(
+ r#"cmd!(sh, "echo a{args...}")"#,
+ "error: can't combine splat with concatenation, add spaces around `{args...}`",
+ );
+}
+
+#[test]
+fn interpolate_splat_concat_suffix() {
+ check(
+ r#"cmd!(sh, "echo {args...}b")"#,
+ "error: can't combine splat with concatenation, add spaces around `{args...}`",
+ );
+}
+
+#[test]
+fn interpolate_splat_concat_mixfix() {
+ check(
+ r#"cmd!(sh, "echo a{args...}b")"#,
+ "error: can't combine splat with concatenation, add spaces around `{args...}`",
+ );
+}
+
+#[test]
+fn empty_command() {
+ check(r#"cmd!(sh, "")"#, "error: command can't be empty");
+}
+
+#[test]
+fn spalt_program() {
+ check(r#"cmd!(sh, "{cmd...}")"#, "error: can't splat program name");
+}
+
+#[test]
+fn unclosed_quote() {
+ check(r#"cmd!(sh, "echo 'hello world")"#, "error: unclosed `'` in command");
+}
+
+#[test]
+fn unclosed_curly() {
+ check(r#"cmd!(sh, "echo {hello world")"#, "error: unclosed `{` in command");
+}
+
+#[test]
+fn interpolate_integer() {
+ check(
+ r#"
+ let x = 92;
+ cmd!(sh, "make -j {x}")"#,
+ r#"is not implemented"#,
+ );
+}
+
+#[test]
+fn splat_fn_pointer() {
+ check(
+ r#"
+ let dry_run: fn() -> Option<&'static str> = || None;
+ cmd!(sh, "make -j {dry_run...}")"#,
+ r#"is not implemented"#,
+ );
+}
diff --git a/vendor/xshell/tests/it/env.rs b/vendor/xshell/tests/it/env.rs
new file mode 100644
index 000000000..949869467
--- /dev/null
+++ b/vendor/xshell/tests/it/env.rs
@@ -0,0 +1,130 @@
+use std::collections::BTreeMap;
+
+use xshell::cmd;
+
+use crate::setup;
+
+#[test]
+fn test_env() {
+ let sh = setup();
+
+ let v1 = "xshell_test_123";
+ let v2 = "xshell_test_456";
+
+ assert_env(cmd!(sh, "xecho -$ {v1}").env(v1, "123"), &[(v1, Some("123"))]);
+
+ assert_env(
+ cmd!(sh, "xecho -$ {v1} {v2}").envs([(v1, "123"), (v2, "456")].iter().copied()),
+ &[(v1, Some("123")), (v2, Some("456"))],
+ );
+ assert_env(
+ cmd!(sh, "xecho -$ {v1} {v2}")
+ .envs([(v1, "123"), (v2, "456")].iter().copied())
+ .env_remove(v2),
+ &[(v1, Some("123")), (v2, None)],
+ );
+ assert_env(
+ cmd!(sh, "xecho -$ {v1} {v2}")
+ .envs([(v1, "123"), (v2, "456")].iter().copied())
+ .env_remove("nothing"),
+ &[(v1, Some("123")), (v2, Some("456"))],
+ );
+
+ let _g1 = sh.push_env(v1, "foobar");
+ let _g2 = sh.push_env(v2, "quark");
+
+ assert_env(cmd!(sh, "xecho -$ {v1} {v2}"), &[(v1, Some("foobar")), (v2, Some("quark"))]);
+
+ assert_env(
+ cmd!(sh, "xecho -$ {v1} {v2}").env(v1, "wombo"),
+ &[(v1, Some("wombo")), (v2, Some("quark"))],
+ );
+
+ assert_env(cmd!(sh, "xecho -$ {v1} {v2}").env_remove(v1), &[(v1, None), (v2, Some("quark"))]);
+ assert_env(
+ cmd!(sh, "xecho -$ {v1} {v2}").env_remove(v1).env(v1, "baz"),
+ &[(v1, Some("baz")), (v2, Some("quark"))],
+ );
+ assert_env(
+ cmd!(sh, "xecho -$ {v1} {v2}").env(v1, "baz").env_remove(v1),
+ &[(v1, None), (v2, Some("quark"))],
+ );
+}
+
+#[test]
+fn test_env_clear() {
+ let sh = setup();
+
+ let v1 = "xshell_test_123";
+ let v2 = "xshell_test_456";
+
+ let xecho = format!("./target/xecho{}", std::env::consts::EXE_SUFFIX);
+
+ assert_env(
+ cmd!(sh, "{xecho} -$ {v1} {v2}")
+ .envs([(v1, "123"), (v2, "456")].iter().copied())
+ .env_clear(),
+ &[(v1, None), (v2, None)],
+ );
+ assert_env(
+ cmd!(sh, "{xecho} -$ {v1} {v2}")
+ .envs([(v1, "123"), (v2, "456")].iter().copied())
+ .env_clear()
+ .env(v1, "789"),
+ &[(v1, Some("789")), (v2, None)],
+ );
+
+ let _g1 = sh.push_env(v1, "foobar");
+ let _g2 = sh.push_env(v2, "quark");
+
+ assert_env(cmd!(sh, "{xecho} -$ {v1} {v2}").env_clear(), &[(v1, None), (v2, None)]);
+ assert_env(
+ cmd!(sh, "{xecho} -$ {v1} {v2}").env_clear().env(v1, "baz"),
+ &[(v1, Some("baz")), (v2, None)],
+ );
+ assert_env(
+ cmd!(sh, "{xecho} -$ {v1} {v2}").env(v1, "baz").env_clear(),
+ &[(v1, None), (v2, None)],
+ );
+}
+
+#[track_caller]
+fn assert_env(xecho_env_cmd: xshell::Cmd, want_env: &[(&str, Option<&str>)]) {
+ let output = xecho_env_cmd.output().unwrap();
+ let env = String::from_utf8_lossy(&output.stdout)
+ .lines()
+ .filter(|line| !line.is_empty())
+ .map(|line| {
+ let (key, val) = line.split_once('=').unwrap_or_else(|| {
+ panic!("failed to parse line from `xecho -$` output: {:?}", line)
+ });
+ (key.to_owned(), val.to_owned())
+ })
+ .collect::<BTreeMap<_, _>>();
+ check_env(&env, want_env);
+}
+
+#[track_caller]
+fn check_env(env: &BTreeMap<String, String>, wanted_env: &[(&str, Option<&str>)]) {
+ let mut failed = false;
+ let mut seen = env.clone();
+ for &(k, val) in wanted_env {
+ match (seen.remove(k), val) {
+ (Some(env_v), Some(want_v)) if env_v == want_v => {}
+ (None, None) => {}
+ (have, want) => {
+ eprintln!("mismatch on env var {:?}: have `{:?}`, want `{:?}` ", k, have, want);
+ failed = true;
+ }
+ }
+ }
+ for (k, v) in seen {
+ eprintln!("Unexpected env key {:?} (value: {:?})", k, v);
+ failed = true;
+ }
+ assert!(
+ !failed,
+ "env didn't match (see stderr for cleaner output):\nsaw: {:?}\n\nwanted: {:?}",
+ env, wanted_env,
+ );
+}
diff --git a/vendor/xshell/tests/it/main.rs b/vendor/xshell/tests/it/main.rs
new file mode 100644
index 000000000..6ac8fe074
--- /dev/null
+++ b/vendor/xshell/tests/it/main.rs
@@ -0,0 +1,462 @@
+mod tidy;
+mod env;
+mod compile_failures;
+
+use std::{ffi::OsStr, path::Path};
+
+use xshell::{cmd, Shell};
+
+fn setup() -> Shell {
+ static ONCE: std::sync::Once = std::sync::Once::new();
+
+ let sh = Shell::new().unwrap();
+ let xecho_src = sh.current_dir().join("./tests/data/xecho.rs");
+ let target_dir = sh.current_dir().join("./target/");
+
+ ONCE.call_once(|| {
+ cmd!(sh, "rustc {xecho_src} --out-dir {target_dir}")
+ .quiet()
+ .run()
+ .unwrap_or_else(|err| panic!("failed to install binaries from mock_bin: {}", err))
+ });
+
+ sh.set_var("PATH", target_dir);
+ sh
+}
+
+#[test]
+fn smoke() {
+ let sh = setup();
+
+ let pwd = "lol";
+ let cmd = cmd!(sh, "xecho 'hello '{pwd}");
+ println!("{}", cmd);
+}
+
+#[test]
+fn into_command() {
+ let sh = setup();
+ let _: std::process::Command = cmd!(sh, "git branch").into();
+}
+
+#[test]
+fn multiline() {
+ let sh = setup();
+
+ let output = cmd!(
+ sh,
+ "
+ xecho hello
+ "
+ )
+ .read()
+ .unwrap();
+ assert_eq!(output, "hello");
+}
+
+#[test]
+fn interpolation() {
+ let sh = setup();
+
+ let hello = "hello";
+ let output = cmd!(sh, "xecho {hello}").read().unwrap();
+ assert_eq!(output, "hello");
+}
+
+#[test]
+fn program_interpolation() {
+ let sh = setup();
+
+ let echo = "xecho";
+ let output = cmd!(sh, "{echo} hello").read().unwrap();
+ assert_eq!(output, "hello");
+}
+
+#[test]
+fn interpolation_concatenation() {
+ let sh = setup();
+
+ let hello = "hello";
+ let world = "world";
+ let output = cmd!(sh, "xecho {hello}-{world}").read().unwrap();
+ assert_eq!(output, "hello-world");
+}
+
+#[test]
+fn program_concatenation() {
+ let sh = setup();
+
+ let ho = "ho";
+ let output = cmd!(sh, "xec{ho} hello").read().unwrap();
+ assert_eq!(output, "hello");
+}
+
+#[test]
+fn interpolation_move() {
+ let sh = setup();
+
+ let hello = "hello".to_string();
+ let output1 = cmd!(sh, "xecho {hello}").read().unwrap();
+ let output2 = cmd!(sh, "xecho {hello}").read().unwrap();
+ assert_eq!(output1, output2)
+}
+
+#[test]
+fn interpolation_spat() {
+ let sh = setup();
+
+ let a = &["hello", "world"];
+ let b: &[&OsStr] = &[];
+ let c = &["!".to_string()];
+ let output = cmd!(sh, "xecho {a...} {b...} {c...}").read().unwrap();
+ assert_eq!(output, "hello world !")
+}
+
+#[test]
+fn splat_option() {
+ let sh = setup();
+
+ let a: Option<&OsStr> = None;
+ let b = Some("hello");
+ let output = cmd!(sh, "xecho {a...} {b...}").read().unwrap();
+ assert_eq!(output, "hello")
+}
+
+#[test]
+fn splat_idiom() {
+ let sh = setup();
+
+ let check = if true { &["--", "--check"][..] } else { &[] };
+ let cmd = cmd!(sh, "cargo fmt {check...}");
+ assert_eq!(cmd.to_string(), "cargo fmt -- --check");
+
+ let dry_run = if true { Some("--dry-run") } else { None };
+ let cmd = cmd!(sh, "cargo publish {dry_run...}");
+ assert_eq!(cmd.to_string(), "cargo publish --dry-run");
+}
+
+#[test]
+fn exit_status() {
+ let sh = setup();
+
+ let err = cmd!(sh, "xecho -f").read().unwrap_err();
+ assert_eq!(err.to_string(), "command exited with non-zero code `xecho -f`: 1");
+}
+
+#[test]
+#[cfg_attr(not(unix), ignore)]
+fn exit_status_signal() {
+ let sh = setup();
+
+ let err = cmd!(sh, "xecho -s").read().unwrap_err();
+ assert_eq!(err.to_string(), "command was terminated by a signal `xecho -s`: 9");
+}
+
+#[test]
+fn ignore_status() {
+ let sh = setup();
+
+ let output = cmd!(sh, "xecho -f").ignore_status().read().unwrap();
+ assert_eq!(output, "");
+}
+
+#[test]
+fn ignore_status_no_such_command() {
+ let sh = setup();
+
+ let err = cmd!(sh, "xecho-f").ignore_status().read().unwrap_err();
+ assert_eq!(err.to_string(), "command not found: `xecho-f`");
+}
+
+#[test]
+#[cfg_attr(not(unix), ignore)]
+fn ignore_status_signal() {
+ let sh = setup();
+
+ let output = cmd!(sh, "xecho -s dead").ignore_status().read().unwrap();
+ assert_eq!(output, "dead");
+}
+
+#[test]
+fn read_stderr() {
+ let sh = setup();
+
+ let output = cmd!(sh, "xecho -f -e snafu").ignore_status().read_stderr().unwrap();
+ assert!(output.contains("snafu"));
+}
+
+#[test]
+fn unknown_command() {
+ let sh = setup();
+
+ let err = cmd!(sh, "nope no way").read().unwrap_err();
+ assert_eq!(err.to_string(), "command not found: `nope`");
+}
+
+#[test]
+fn args_with_spaces() {
+ let sh = setup();
+
+ let hello_world = "hello world";
+ let cmd = cmd!(sh, "xecho {hello_world} 'hello world' hello world");
+ assert_eq!(cmd.to_string(), r#"xecho "hello world" "hello world" hello world"#)
+}
+
+#[test]
+fn escape() {
+ let sh = setup();
+
+ let output = cmd!(sh, "xecho \\hello\\ '\\world\\'").read().unwrap();
+ assert_eq!(output, r#"\hello\ \world\"#)
+}
+
+#[test]
+fn stdin_redirection() {
+ let sh = setup();
+
+ let lines = "\
+foo
+baz
+bar
+";
+ let output = cmd!(sh, "xecho -i").stdin(lines).read().unwrap().replace("\r\n", "\n");
+ assert_eq!(
+ output,
+ "\
+foo
+baz
+bar"
+ )
+}
+
+#[test]
+fn no_deadlock() {
+ let sh = setup();
+
+ let mut data = "All the work and now paly made Jack a dull boy.\n".repeat(1 << 20);
+ data.pop();
+ let res = cmd!(sh, "xecho -i").stdin(&data).read().unwrap();
+ assert_eq!(data, res);
+}
+
+#[test]
+fn test_push_dir() {
+ let sh = setup();
+
+ let d1 = sh.current_dir();
+ {
+ let _p = sh.push_dir("xshell-macros");
+ let d2 = sh.current_dir();
+ assert_eq!(d2, d1.join("xshell-macros"));
+ {
+ let _p = sh.push_dir("src");
+ let d3 = sh.current_dir();
+ assert_eq!(d3, d1.join("xshell-macros/src"));
+ }
+ let d4 = sh.current_dir();
+ assert_eq!(d4, d1.join("xshell-macros"));
+ }
+ let d5 = sh.current_dir();
+ assert_eq!(d5, d1);
+}
+
+#[test]
+fn test_push_and_change_dir() {
+ let sh = setup();
+
+ let d1 = sh.current_dir();
+ {
+ let _p = sh.push_dir("xshell-macros");
+ let d2 = sh.current_dir();
+ assert_eq!(d2, d1.join("xshell-macros"));
+ sh.change_dir("src");
+ let d3 = sh.current_dir();
+ assert_eq!(d3, d1.join("xshell-macros/src"));
+ }
+ let d5 = sh.current_dir();
+ assert_eq!(d5, d1);
+}
+
+#[test]
+fn push_dir_parent_dir() {
+ let sh = setup();
+
+ let current = sh.current_dir();
+ let dirname = current.file_name().unwrap();
+ let _d = sh.push_dir("..");
+ let _d = sh.push_dir(dirname);
+ assert_eq!(sh.current_dir().canonicalize().unwrap(), current.canonicalize().unwrap());
+}
+
+const VAR: &str = "SPICA";
+
+#[test]
+fn test_push_env() {
+ let sh = setup();
+
+ let e1 = sh.var_os(VAR);
+ {
+ let _e = sh.push_env(VAR, "1");
+ let e2 = sh.var_os(VAR);
+ assert_eq!(e2, Some("1".into()));
+ {
+ let _e = sh.push_env(VAR, "2");
+ let e3 = sh.var_os(VAR);
+ assert_eq!(e3, Some("2".into()));
+ }
+ let e4 = sh.var_os(VAR);
+ assert_eq!(e4, e2);
+ }
+ let e5 = sh.var_os(VAR);
+ assert_eq!(e5, e1);
+}
+
+#[test]
+fn test_push_env_and_set_var() {
+ let sh = setup();
+
+ let e1 = sh.var_os(VAR);
+ {
+ let _e = sh.push_env(VAR, "1");
+ let e2 = sh.var_os(VAR);
+ assert_eq!(e2, Some("1".into()));
+ let _e = sh.set_var(VAR, "2");
+ let e3 = sh.var_os(VAR);
+ assert_eq!(e3, Some("2".into()));
+ }
+ let e5 = sh.var_os(VAR);
+ assert_eq!(e5, e1);
+}
+
+#[test]
+fn output_with_ignore() {
+ let sh = setup();
+
+ let output = cmd!(sh, "xecho -e 'hello world!'").ignore_stdout().output().unwrap();
+ assert_eq!(output.stderr, b"hello world!\n");
+ assert_eq!(output.stdout, b"");
+
+ let output = cmd!(sh, "xecho -e 'hello world!'").ignore_stderr().output().unwrap();
+ assert_eq!(output.stdout, b"hello world!\n");
+ assert_eq!(output.stderr, b"");
+
+ let output =
+ cmd!(sh, "xecho -e 'hello world!'").ignore_stdout().ignore_stderr().output().unwrap();
+ assert_eq!(output.stdout, b"");
+ assert_eq!(output.stderr, b"");
+}
+
+#[test]
+fn test_read_with_ignore() {
+ let sh = setup();
+
+ let stdout = cmd!(sh, "xecho -e 'hello world'").ignore_stdout().read().unwrap();
+ assert!(stdout.is_empty());
+
+ let stderr = cmd!(sh, "xecho -e 'hello world'").ignore_stderr().read_stderr().unwrap();
+ assert!(stderr.is_empty());
+
+ let stdout = cmd!(sh, "xecho -e 'hello world!'").ignore_stderr().read().unwrap();
+ assert_eq!(stdout, "hello world!");
+
+ let stderr = cmd!(sh, "xecho -e 'hello world!'").ignore_stdout().read_stderr().unwrap();
+ assert_eq!(stderr, "hello world!");
+}
+
+#[test]
+fn test_copy_file() {
+ let sh = setup();
+
+ let path;
+ {
+ let tempdir = sh.create_temp_dir().unwrap();
+ path = tempdir.path().to_path_buf();
+ let foo = tempdir.path().join("foo.txt");
+ let bar = tempdir.path().join("bar.txt");
+ let dir = tempdir.path().join("dir");
+ sh.write_file(&foo, "hello world").unwrap();
+ sh.create_dir(&dir).unwrap();
+
+ sh.copy_file(&foo, &bar).unwrap();
+ assert_eq!(sh.read_file(&bar).unwrap(), "hello world");
+
+ sh.copy_file(&foo, &dir).unwrap();
+ assert_eq!(sh.read_file(&dir.join("foo.txt")).unwrap(), "hello world");
+ assert!(path.exists());
+ }
+ assert!(!path.exists());
+}
+
+#[test]
+fn test_exists() {
+ let sh = setup();
+ let tmp = sh.create_temp_dir().unwrap();
+ let _d = sh.change_dir(tmp.path());
+ assert!(!sh.path_exists("foo.txt"));
+ sh.write_file("foo.txt", "foo").unwrap();
+ assert!(sh.path_exists("foo.txt"));
+ assert!(!sh.path_exists("bar"));
+ sh.create_dir("bar").unwrap();
+ assert!(sh.path_exists("bar"));
+ let _d = sh.change_dir("bar");
+ assert!(!sh.path_exists("quz.rs"));
+ sh.write_file("quz.rs", "fn main () {}").unwrap();
+ assert!(sh.path_exists("quz.rs"));
+ sh.remove_path("quz.rs").unwrap();
+ assert!(!sh.path_exists("quz.rs"));
+}
+
+#[test]
+fn write_makes_directory() {
+ let sh = setup();
+
+ let tempdir = sh.create_temp_dir().unwrap();
+ let folder = tempdir.path().join("some/nested/folder/structure");
+ sh.write_file(folder.join(".gitinclude"), "").unwrap();
+ assert!(folder.exists());
+}
+
+#[test]
+fn test_remove_path() {
+ let sh = setup();
+
+ let tempdir = sh.create_temp_dir().unwrap();
+ sh.change_dir(tempdir.path());
+ sh.write_file(Path::new("a/b/c.rs"), "fn main() {}").unwrap();
+ assert!(tempdir.path().join("a/b/c.rs").exists());
+ sh.remove_path("./a").unwrap();
+ assert!(!tempdir.path().join("a/b/c.rs").exists());
+ sh.remove_path("./a").unwrap();
+}
+
+#[test]
+fn recovers_from_panics() {
+ let sh = setup();
+
+ let tempdir = sh.create_temp_dir().unwrap();
+ let tempdir = tempdir.path().canonicalize().unwrap();
+
+ let orig = sh.current_dir();
+
+ std::panic::catch_unwind(|| {
+ let _p = sh.push_dir(&tempdir);
+ assert_eq!(sh.current_dir(), tempdir);
+ std::panic::resume_unwind(Box::new(()));
+ })
+ .unwrap_err();
+
+ assert_eq!(sh.current_dir(), orig);
+ {
+ let _p = sh.push_dir(&tempdir);
+ assert_eq!(sh.current_dir(), tempdir);
+ }
+}
+
+#[test]
+fn string_escapes() {
+ let sh = setup();
+
+ assert_eq!(cmd!(sh, "\"hello\"").to_string(), "\"hello\"");
+ assert_eq!(cmd!(sh, "\"\"\"asdf\"\"\"").to_string(), r##""""asdf""""##);
+ assert_eq!(cmd!(sh, "\\\\").to_string(), r#"\\"#);
+}
diff --git a/vendor/xshell/tests/it/tidy.rs b/vendor/xshell/tests/it/tidy.rs
new file mode 100644
index 000000000..2b55b2907
--- /dev/null
+++ b/vendor/xshell/tests/it/tidy.rs
@@ -0,0 +1,37 @@
+use xshell::{cmd, Shell};
+
+#[test]
+fn versions_match() {
+ let sh = Shell::new().unwrap();
+
+ let read_version = |path: &str| {
+ let text = sh.read_file(path).unwrap();
+ let vers = text.lines().find(|it| it.starts_with("version =")).unwrap();
+ let vers = vers.splitn(2, '#').next().unwrap();
+ vers.trim_start_matches("version =").trim().trim_matches('"').to_string()
+ };
+
+ let v1 = read_version("./Cargo.toml");
+ let v2 = read_version("./xshell-macros/Cargo.toml");
+ assert_eq!(v1, v2);
+
+ let cargo_toml = sh.read_file("./Cargo.toml").unwrap();
+ let dep = format!("xshell-macros = {{ version = \"={}\",", v1);
+ assert!(cargo_toml.contains(&dep));
+}
+
+#[test]
+fn formatting() {
+ let sh = Shell::new().unwrap();
+
+ cmd!(sh, "cargo fmt --all -- --check").run().unwrap()
+}
+
+#[test]
+fn current_version_in_changelog() {
+ let sh = Shell::new().unwrap();
+ let _p = sh.push_dir(env!("CARGO_MANIFEST_DIR"));
+ let changelog = sh.read_file("CHANGELOG.md").unwrap();
+ let current_version_header = format!("## {}", env!("CARGO_PKG_VERSION"));
+ assert_eq!(changelog.lines().filter(|&line| line == current_version_header).count(), 1);
+}