diff --git a/shpool/tests/attach.rs b/shpool/tests/attach.rs index a9b9a9dd..79f69d90 100644 --- a/shpool/tests/attach.rs +++ b/shpool/tests/attach.rs @@ -24,148 +24,108 @@ use crate::support::{ #[test] #[timeout(30000)] fn happy_path() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) - .context("starting daemon proc")?; - let mut attach_proc = - daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; + let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) + .context("starting daemon proc")?; + let mut attach_proc = + daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; - // not really needed, just here to test the events system - attach_proc.await_event("attach-startup")?; + // not really needed, just here to test the events system + attach_proc.await_event("attach-startup")?; - let mut line_matcher = attach_proc.line_matcher()?; + let mut line_matcher = attach_proc.line_matcher()?; - // not really needed, just here to test the events system - daemon_proc.await_event("daemon-about-to-listen")?; + // not really needed, just here to test the events system + daemon_proc.await_event("daemon-about-to-listen")?; - attach_proc.run_cmd("echo hi")?; - line_matcher.scan_until_re("hi$")?; + attach_proc.run_cmd("echo hi")?; + line_matcher.scan_until_re("hi$")?; - attach_proc.run_cmd("echo ping")?; - line_matcher.match_re("ping$")?; + attach_proc.run_cmd("echo ping")?; + line_matcher.match_re("ping$")?; - // make sure that shpool sets a $USER variable - attach_proc.run_cmd(r#"echo "user=$USER" "#)?; - line_matcher.match_re("user=[a-zA-Z0-9]+$")?; + // make sure that shpool sets a $USER variable + attach_proc.run_cmd(r#"echo "user=$USER" "#)?; + line_matcher.match_re("user=[a-zA-Z0-9]+$")?; - // make sure that shpool sets the $SHELL variable - attach_proc.run_cmd(r#"echo "shell=$SHELL" "#)?; - line_matcher.match_re("shell=[/a-zA-Z0-9]+$")?; + // make sure that shpool sets the $SHELL variable + attach_proc.run_cmd(r#"echo "shell=$SHELL" "#)?; + line_matcher.match_re("shell=[/a-zA-Z0-9]+$")?; - Ok(()) - }) + Ok(()) } #[test] #[timeout(30000)] fn custom_cmd() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) - .context("starting daemon proc")?; - let script = support::testdata_file("echo_stop.sh"); - let mut attach_proc = daemon_proc - .attach( - "sh1", - AttachArgs { - cmd: Some(format!("{} foo", script.into_os_string().into_string().unwrap())), - ..Default::default() - }, - ) - .context("starting attach proc")?; - let mut line_matcher = attach_proc.line_matcher()?; + let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) + .context("starting daemon proc")?; + let script = support::testdata_file("echo_stop.sh"); + let mut attach_proc = daemon_proc + .attach( + "sh1", + AttachArgs { + cmd: Some(format!("{} foo", script.into_os_string().into_string().unwrap())), + ..Default::default() + }, + ) + .context("starting attach proc")?; + let mut line_matcher = attach_proc.line_matcher()?; - // the script first echos the arg we gave it - line_matcher.match_re("foo$")?; + // the script first echos the arg we gave it + line_matcher.match_re("foo$")?; - // then it echos its argv[0] so we can make sure it has not been re-written - // to '-echo_stop.sh' like it would for a login shell - line_matcher.match_re(r#"\/echo_stop\.sh$"#)?; + // then it echos its argv[0] so we can make sure it has not been re-written + // to '-echo_stop.sh' like it would for a login shell + line_matcher.match_re(r#"\/echo_stop\.sh$"#)?; - // then waits until we tell it to bail (so we can avoid sleeps) - attach_proc.run_cmd("stop")?; + // then waits until we tell it to bail (so we can avoid sleeps) + attach_proc.run_cmd("stop")?; - Ok(()) - }) + Ok(()) } #[test] #[timeout(30000)] fn forward_env() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new("forward_env.toml", DaemonArgs::default()) - .context("starting daemon proc")?; + let mut daemon_proc = support::daemon::Proc::new("forward_env.toml", DaemonArgs::default()) + .context("starting daemon proc")?; - let bidi_done_w = daemon_proc.events.take().unwrap().waiter(["daemon-bidi-stream-done"]); - { - let mut attach_proc = daemon_proc - .attach( - "sh1", - AttachArgs { - extra_env: vec![ - (String::from("FOO"), String::from("foo")), // forwarded - (String::from("BAR"), String::from("bar")), // forwarded - (String::from("BAZ"), String::from("baz")), // not forwarded - ], - ..Default::default() - }, - ) - .context("starting attach proc")?; - - let mut line_matcher = attach_proc.line_matcher()?; - - attach_proc.run_cmd(r#"echo "$FOO:$BAR:$BAZ" "#)?; - line_matcher.scan_until_re("foo:bar:$")?; - } - - // wait until the daemon has noticed that the connection - // has dropped before we attempt to open the connection again - daemon_proc.events = Some(bidi_done_w.wait_final_event("daemon-bidi-stream-done")?); + let bidi_done_w = daemon_proc.events.take().unwrap().waiter(["daemon-bidi-stream-done"]); + { + let mut attach_proc = daemon_proc + .attach( + "sh1", + AttachArgs { + extra_env: vec![ + (String::from("FOO"), String::from("foo")), // forwarded + (String::from("BAR"), String::from("bar")), // forwarded + (String::from("BAZ"), String::from("baz")), // not forwarded + ], + ..Default::default() + }, + ) + .context("starting attach proc")?; - { - let mut attach_proc = daemon_proc - .attach( - "sh1", - AttachArgs { - extra_env: vec![ - (String::from("FOO"), String::from("foonew")), // forwarded - (String::from("BAR"), String::from("bar")), // forwarded - (String::from("BAZ"), String::from("baz")), // not forwarded - ], - ..Default::default() - }, - ) - .context("starting attach proc")?; - - let mut line_matcher = attach_proc.line_matcher()?; - - attach_proc.run_cmd(r#"source $SHPOOL_SESSION_DIR/forward.env "#)?; - attach_proc.run_cmd(r#"echo "$FOO:$BAR:$BAZ" "#)?; - line_matcher.scan_until_re("foonew:bar:$")?; - } - - Ok(()) - }) -} + let mut line_matcher = attach_proc.line_matcher()?; -#[test] -#[timeout(30000)] -fn symlink_ssh_auth_sock() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) - .context("starting daemon proc")?; - let mut waiter = daemon_proc.events.take().unwrap().waiter(["daemon-wrote-s2c-chunk"]); + attach_proc.run_cmd(r#"echo "$FOO:$BAR:$BAZ" "#)?; + line_matcher.scan_until_re("foo:bar:$")?; + } - let fake_auth_sock_tgt = daemon_proc.tmp_dir.path().join("ssh-auth-sock-target.fake"); - fs::File::create(&fake_auth_sock_tgt)?; + // wait until the daemon has noticed that the connection + // has dropped before we attempt to open the connection again + daemon_proc.events = Some(bidi_done_w.wait_final_event("daemon-bidi-stream-done")?); + { let mut attach_proc = daemon_proc .attach( "sh1", AttachArgs { - extra_env: vec![( - String::from("SSH_AUTH_SOCK"), - String::from(fake_auth_sock_tgt.to_str().unwrap()), - )], + extra_env: vec![ + (String::from("FOO"), String::from("foonew")), // forwarded + (String::from("BAR"), String::from("bar")), // forwarded + (String::from("BAZ"), String::from("baz")), // not forwarded + ], ..Default::default() }, ) @@ -173,94 +133,118 @@ fn symlink_ssh_auth_sock() -> anyhow::Result<()> { let mut line_matcher = attach_proc.line_matcher()?; - waiter.wait_event("daemon-wrote-s2c-chunk")?; // resize prompt redraw - attach_proc.run_cmd("ls -l $SSH_AUTH_SOCK")?; - line_matcher - .scan_until_re(r#".*sh1/ssh-auth-sock.socket ->.*ssh-auth-sock-target.fake$"#)?; + attach_proc.run_cmd(r#"source $SHPOOL_SESSION_DIR/forward.env "#)?; + attach_proc.run_cmd(r#"echo "$FOO:$BAR:$BAZ" "#)?; + line_matcher.scan_until_re("foonew:bar:$")?; + } + + Ok(()) +} + +#[test] +#[timeout(30000)] +fn symlink_ssh_auth_sock() -> anyhow::Result<()> { + let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) + .context("starting daemon proc")?; + let mut waiter = daemon_proc.events.take().unwrap().waiter(["daemon-wrote-s2c-chunk"]); + + let fake_auth_sock_tgt = daemon_proc.tmp_dir.path().join("ssh-auth-sock-target.fake"); + fs::File::create(&fake_auth_sock_tgt)?; + + let mut attach_proc = daemon_proc + .attach( + "sh1", + AttachArgs { + extra_env: vec![( + String::from("SSH_AUTH_SOCK"), + String::from(fake_auth_sock_tgt.to_str().unwrap()), + )], + ..Default::default() + }, + ) + .context("starting attach proc")?; + + let mut line_matcher = attach_proc.line_matcher()?; + + waiter.wait_event("daemon-wrote-s2c-chunk")?; // resize prompt redraw + attach_proc.run_cmd("ls -l $SSH_AUTH_SOCK")?; + line_matcher.scan_until_re(r#".*sh1/ssh-auth-sock.socket ->.*ssh-auth-sock-target.fake$"#)?; - Ok(()) - }) + Ok(()) } #[test] #[timeout(30000)] fn missing_ssh_auth_sock() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) - .context("starting daemon proc")?; - let mut waiter = daemon_proc.events.take().unwrap().waiter(["daemon-wrote-s2c-chunk"]); + let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) + .context("starting daemon proc")?; + let mut waiter = daemon_proc.events.take().unwrap().waiter(["daemon-wrote-s2c-chunk"]); - let fake_auth_sock_tgt = daemon_proc.tmp_dir.path().join("ssh-auth-sock-target.fake"); - fs::File::create(fake_auth_sock_tgt)?; + let fake_auth_sock_tgt = daemon_proc.tmp_dir.path().join("ssh-auth-sock-target.fake"); + fs::File::create(fake_auth_sock_tgt)?; - let mut attach_proc = - daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; + let mut attach_proc = + daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; - let mut line_matcher = attach_proc.line_matcher()?; + let mut line_matcher = attach_proc.line_matcher()?; - waiter.wait_event("daemon-wrote-s2c-chunk")?; // resize prompt re-draw - attach_proc.run_cmd("ls -l $SSH_AUTH_SOCK")?; - line_matcher.scan_until_re(r#".*No such file or directory$"#)?; + waiter.wait_event("daemon-wrote-s2c-chunk")?; // resize prompt re-draw + attach_proc.run_cmd("ls -l $SSH_AUTH_SOCK")?; + line_matcher.scan_until_re(r#".*No such file or directory$"#)?; - Ok(()) - }) + Ok(()) } #[test] #[timeout(30000)] fn fresh_shell_draws_prompt() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) - .context("starting daemon proc")?; + let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) + .context("starting daemon proc")?; - let mut attach_proc = - daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; - let mut reader = std::io::BufReader::new( - attach_proc.proc.stdout.take().ok_or(anyhow!("missing stdout"))?, - ); + let mut attach_proc = + daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; + let mut reader = + std::io::BufReader::new(attach_proc.proc.stdout.take().ok_or(anyhow!("missing stdout"))?); - let mut output = vec![]; - reader.read_until(b'>', &mut output)?; - let chunk = String::from_utf8_lossy(&output[..]); - assert!(chunk.contains("prompt")); + let mut output = vec![]; + reader.read_until(b'>', &mut output)?; + let chunk = String::from_utf8_lossy(&output[..]); + assert!(chunk.contains("prompt")); - Ok(()) - }) + Ok(()) } #[test] #[timeout(30000)] fn config_disable_symlink_ssh_auth_sock() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = - support::daemon::Proc::new("disable_symlink_ssh_auth_sock.toml", DaemonArgs::default()) - .context("starting daemon proc")?; - let mut waiter = daemon_proc.events.take().unwrap().waiter(["daemon-wrote-s2c-chunk"]); + let mut daemon_proc = + support::daemon::Proc::new("disable_symlink_ssh_auth_sock.toml", DaemonArgs::default()) + .context("starting daemon proc")?; + let mut waiter = daemon_proc.events.take().unwrap().waiter(["daemon-wrote-s2c-chunk"]); - let fake_auth_sock_tgt = daemon_proc.tmp_dir.path().join("ssh-auth-sock-target.fake"); - fs::File::create(&fake_auth_sock_tgt)?; + let fake_auth_sock_tgt = daemon_proc.tmp_dir.path().join("ssh-auth-sock-target.fake"); + fs::File::create(&fake_auth_sock_tgt)?; - let mut attach_proc = daemon_proc - .attach( - "sh1", - AttachArgs { - extra_env: vec![( - String::from("SSH_AUTH_SOCK"), - String::from(fake_auth_sock_tgt.to_str().unwrap()), - )], - ..Default::default() - }, - ) - .context("starting attach proc")?; + let mut attach_proc = daemon_proc + .attach( + "sh1", + AttachArgs { + extra_env: vec![( + String::from("SSH_AUTH_SOCK"), + String::from(fake_auth_sock_tgt.to_str().unwrap()), + )], + ..Default::default() + }, + ) + .context("starting attach proc")?; - let mut line_matcher = attach_proc.line_matcher()?; + let mut line_matcher = attach_proc.line_matcher()?; - waiter.wait_event("daemon-wrote-s2c-chunk")?; // resize prompt re-draw - attach_proc.run_cmd("ls -l $SSH_AUTH_SOCK")?; - line_matcher.scan_until_re(r#".*No such file or directory$"#)?; + waiter.wait_event("daemon-wrote-s2c-chunk")?; // resize prompt re-draw + attach_proc.run_cmd("ls -l $SSH_AUTH_SOCK")?; + line_matcher.scan_until_re(r#".*No such file or directory$"#)?; - Ok(()) - }) + Ok(()) } // test the attach process getting killed, then re-attaching to the @@ -268,63 +252,57 @@ fn config_disable_symlink_ssh_auth_sock() -> anyhow::Result<()> { #[test] #[timeout(30000)] fn bounce() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) - .context("starting daemon proc")?; + let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) + .context("starting daemon proc")?; - let bidi_done_w = daemon_proc.events.take().unwrap().waiter(["daemon-bidi-stream-done"]); - { - let mut attach_proc = - daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; + let bidi_done_w = daemon_proc.events.take().unwrap().waiter(["daemon-bidi-stream-done"]); + { + let mut attach_proc = + daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; - let mut line_matcher = attach_proc.line_matcher()?; + let mut line_matcher = attach_proc.line_matcher()?; - attach_proc.run_cmd("export MYVAR=1")?; - attach_proc.run_cmd("echo $MYVAR")?; - line_matcher.scan_until_re("1$")?; - } // falling out of scope kills attach_proc + attach_proc.run_cmd("export MYVAR=1")?; + attach_proc.run_cmd("echo $MYVAR")?; + line_matcher.scan_until_re("1$")?; + } // falling out of scope kills attach_proc - // wait until the daemon has noticed that the connection - // has dropped before we attempt to open the connection again - daemon_proc.events = Some(bidi_done_w.wait_final_event("daemon-bidi-stream-done")?); + // wait until the daemon has noticed that the connection + // has dropped before we attempt to open the connection again + daemon_proc.events = Some(bidi_done_w.wait_final_event("daemon-bidi-stream-done")?); - { - let mut attach_proc = - daemon_proc.attach("sh1", Default::default()).context("reattaching")?; + { + let mut attach_proc = + daemon_proc.attach("sh1", Default::default()).context("reattaching")?; - let mut line_matcher = attach_proc.line_matcher()?; + let mut line_matcher = attach_proc.line_matcher()?; - attach_proc.run_cmd("echo $MYVAR")?; - line_matcher.match_re("1$")?; - } + attach_proc.run_cmd("echo $MYVAR")?; + line_matcher.match_re("1$")?; + } - Ok(()) - }) + Ok(()) } #[test] #[timeout(30000)] fn two_at_once() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) - .context("starting daemon proc")?; + let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) + .context("starting daemon proc")?; - let mut attach_proc1 = - daemon_proc.attach("sh1", Default::default()).context("starting sh1")?; - let mut line_matcher1 = attach_proc1.line_matcher()?; + let mut attach_proc1 = daemon_proc.attach("sh1", Default::default()).context("starting sh1")?; + let mut line_matcher1 = attach_proc1.line_matcher()?; - let mut attach_proc2 = - daemon_proc.attach("sh2", Default::default()).context("starting sh2")?; - let mut line_matcher2 = attach_proc2.line_matcher()?; + let mut attach_proc2 = daemon_proc.attach("sh2", Default::default()).context("starting sh2")?; + let mut line_matcher2 = attach_proc2.line_matcher()?; - attach_proc1.run_cmd("echo proc1").context("proc1 echo")?; - line_matcher1.scan_until_re("proc1$").context("proc1 match")?; + attach_proc1.run_cmd("echo proc1").context("proc1 echo")?; + line_matcher1.scan_until_re("proc1$").context("proc1 match")?; - attach_proc2.run_cmd("echo proc2").context("proc2 echo")?; - line_matcher2.scan_until_re("proc2$").context("proc2 match")?; + attach_proc2.run_cmd("echo proc2").context("proc2 echo")?; + line_matcher2.scan_until_re("proc2$").context("proc2 match")?; - Ok(()) - }) + Ok(()) } // test the attach process getting killed, then re-attaching to the @@ -332,40 +310,38 @@ fn two_at_once() -> anyhow::Result<()> { #[test] #[timeout(30000)] fn explicit_exit() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) - .context("starting daemon proc")?; + let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) + .context("starting daemon proc")?; - let bidi_done_w = daemon_proc.events.take().unwrap().waiter(["daemon-bidi-stream-done"]); - { - let mut attach_proc = - daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; + let bidi_done_w = daemon_proc.events.take().unwrap().waiter(["daemon-bidi-stream-done"]); + { + let mut attach_proc = + daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; - let mut line_matcher = attach_proc.line_matcher()?; + let mut line_matcher = attach_proc.line_matcher()?; - attach_proc.run_cmd("export MYVAR=first")?; - attach_proc.run_cmd("echo $MYVAR")?; - line_matcher.scan_until_re("first$")?; + attach_proc.run_cmd("export MYVAR=first")?; + attach_proc.run_cmd("echo $MYVAR")?; + line_matcher.scan_until_re("first$")?; - attach_proc.run_cmd("exit")?; + attach_proc.run_cmd("exit")?; - // wait until the daemon has cleaned up before dropping - // and explicitly killing the attach proc. - daemon_proc.events = Some(bidi_done_w.wait_final_event("daemon-bidi-stream-done")?); - } + // wait until the daemon has cleaned up before dropping + // and explicitly killing the attach proc. + daemon_proc.events = Some(bidi_done_w.wait_final_event("daemon-bidi-stream-done")?); + } - { - let mut attach_proc = - daemon_proc.attach("sh1", Default::default()).context("reattaching")?; + { + let mut attach_proc = + daemon_proc.attach("sh1", Default::default()).context("reattaching")?; - let mut line_matcher = attach_proc.line_matcher()?; + let mut line_matcher = attach_proc.line_matcher()?; - attach_proc.run_cmd("echo ${MYVAR:-second}")?; - line_matcher.scan_until_re("second$")?; - } + attach_proc.run_cmd("echo ${MYVAR:-second}")?; + line_matcher.scan_until_re("second$")?; + } - Ok(()) - }) + Ok(()) } // Test the attach process getting killed, then re-attaching to the @@ -374,233 +350,213 @@ fn explicit_exit() -> anyhow::Result<()> { #[test] #[timeout(30000)] fn exit_immediate_drop() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) - .context("starting daemon proc")?; + let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) + .context("starting daemon proc")?; - let mut waiter = daemon_proc.events.take().unwrap().waiter([ - "daemon-read-c2s-chunk", - "daemon-read-c2s-chunk", - "daemon-wrote-s2c-chunk", - "daemon-read-c2s-chunk", - "daemon-wrote-s2c-chunk", - "daemon-bidi-stream-done", - ]); + let mut waiter = daemon_proc.events.take().unwrap().waiter([ + "daemon-read-c2s-chunk", + "daemon-read-c2s-chunk", + "daemon-wrote-s2c-chunk", + "daemon-read-c2s-chunk", + "daemon-wrote-s2c-chunk", + "daemon-bidi-stream-done", + ]); - { - let mut attach_proc = - daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; + { + let mut attach_proc = + daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; - let mut line_matcher = attach_proc.line_matcher()?; + let mut line_matcher = attach_proc.line_matcher()?; - attach_proc.run_cmd("export MYVAR=first")?; - waiter.wait_event("daemon-read-c2s-chunk")?; + attach_proc.run_cmd("export MYVAR=first")?; + waiter.wait_event("daemon-read-c2s-chunk")?; - attach_proc.run_cmd("echo $MYVAR")?; - waiter.wait_event("daemon-read-c2s-chunk")?; - line_matcher.match_re("first$")?; - waiter.wait_event("daemon-wrote-s2c-chunk")?; + attach_proc.run_cmd("echo $MYVAR")?; + waiter.wait_event("daemon-read-c2s-chunk")?; + line_matcher.match_re("first$")?; + waiter.wait_event("daemon-wrote-s2c-chunk")?; - attach_proc.run_cmd("exit")?; - waiter.wait_event("daemon-read-c2s-chunk")?; - line_matcher.match_re("logout$")?; - waiter.wait_event("daemon-wrote-s2c-chunk")?; + attach_proc.run_cmd("exit")?; + waiter.wait_event("daemon-read-c2s-chunk")?; + line_matcher.match_re("logout$")?; + waiter.wait_event("daemon-wrote-s2c-chunk")?; - // Immediately kill the attach proc after we've written exit - // to bring the connection down. - } + // Immediately kill the attach proc after we've written exit + // to bring the connection down. + } - daemon_proc.events = Some(waiter.wait_final_event("daemon-bidi-stream-done")?); + daemon_proc.events = Some(waiter.wait_final_event("daemon-bidi-stream-done")?); - { - let mut attach_proc = - daemon_proc.attach("sh1", Default::default()).context("reattaching")?; + { + let mut attach_proc = + daemon_proc.attach("sh1", Default::default()).context("reattaching")?; - let mut line_matcher = attach_proc.line_matcher()?; + let mut line_matcher = attach_proc.line_matcher()?; - attach_proc.run_cmd("echo ${MYVAR:-second}")?; - line_matcher.match_re("second$").context("matching second")?; - } + attach_proc.run_cmd("echo ${MYVAR:-second}")?; + line_matcher.match_re("second$").context("matching second")?; + } - Ok(()) - }) + Ok(()) } #[test] #[timeout(30000)] fn output_flood() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new( - "norc.toml", - DaemonArgs { listen_events: false, ..DaemonArgs::default() }, - ) - .context("starting daemon proc")?; - let mut attach_proc = - daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; + let mut daemon_proc = support::daemon::Proc::new( + "norc.toml", + DaemonArgs { listen_events: false, ..DaemonArgs::default() }, + ) + .context("starting daemon proc")?; + let mut attach_proc = + daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; - attach_proc.run_cmd("cat /dev/urandom | hexdump")?; + attach_proc.run_cmd("cat /dev/urandom | hexdump")?; - let flood_duration = time::Duration::from_secs(2); - let start_time = time::Instant::now(); - let mut stdout = attach_proc.proc.stdout.take().unwrap(); - let mut buf: [u8; 1024 * 256] = [0; 1024 * 256]; - while time::Instant::now().duration_since(start_time) < flood_duration { - stdout.read(&mut buf).context("reading a chunk of flood output")?; - } + let flood_duration = time::Duration::from_secs(2); + let start_time = time::Instant::now(); + let mut stdout = attach_proc.proc.stdout.take().unwrap(); + let mut buf: [u8; 1024 * 256] = [0; 1024 * 256]; + while time::Instant::now().duration_since(start_time) < flood_duration { + stdout.read(&mut buf).context("reading a chunk of flood output")?; + } - Ok(()) - }) + Ok(()) } #[test] #[timeout(30000)] fn force_attach() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new( - "norc.toml", - DaemonArgs { listen_events: false, ..DaemonArgs::default() }, - ) - .context("starting daemon proc")?; + let mut daemon_proc = support::daemon::Proc::new( + "norc.toml", + DaemonArgs { listen_events: false, ..DaemonArgs::default() }, + ) + .context("starting daemon proc")?; + + let mut tty1 = daemon_proc.attach("sh1", Default::default()).context("attaching from tty1")?; + let mut line_matcher1 = tty1.line_matcher()?; + tty1.run_cmd("export MYVAR='set_from_tty1'")?; + tty1.run_cmd("echo $MYVAR")?; + // read some output to make sure the var is set by the time + // we force-attach + line_matcher1.scan_until_re("set_from_tty1$")?; + + let mut tty2 = daemon_proc + .attach("sh1", AttachArgs { force: true, ..Default::default() }) + .context("attaching from tty2")?; + let mut line_matcher2 = tty2.line_matcher()?; + tty2.run_cmd("echo $MYVAR")?; + line_matcher2.match_re("set_from_tty1$")?; - let mut tty1 = - daemon_proc.attach("sh1", Default::default()).context("attaching from tty1")?; - let mut line_matcher1 = tty1.line_matcher()?; - tty1.run_cmd("export MYVAR='set_from_tty1'")?; - tty1.run_cmd("echo $MYVAR")?; - // read some output to make sure the var is set by the time - // we force-attach - line_matcher1.scan_until_re("set_from_tty1$")?; - - let mut tty2 = daemon_proc - .attach("sh1", AttachArgs { force: true, ..Default::default() }) - .context("attaching from tty2")?; - let mut line_matcher2 = tty2.line_matcher()?; - tty2.run_cmd("echo $MYVAR")?; - line_matcher2.match_re("set_from_tty1$")?; - - Ok(()) - }) + Ok(()) } #[test] #[timeout(30000)] fn busy() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new( - "norc.toml", - DaemonArgs { listen_events: false, ..DaemonArgs::default() }, - ) - .context("starting daemon proc")?; + let mut daemon_proc = support::daemon::Proc::new( + "norc.toml", + DaemonArgs { listen_events: false, ..DaemonArgs::default() }, + ) + .context("starting daemon proc")?; - let mut tty1 = - daemon_proc.attach("sh1", Default::default()).context("attaching from tty1")?; - let mut line_matcher1 = tty1.line_matcher()?; - tty1.run_cmd("echo foo")?; // make sure the shell is up and running - line_matcher1.scan_until_re("foo$")?; + let mut tty1 = daemon_proc.attach("sh1", Default::default()).context("attaching from tty1")?; + let mut line_matcher1 = tty1.line_matcher()?; + tty1.run_cmd("echo foo")?; // make sure the shell is up and running + line_matcher1.scan_until_re("foo$")?; - let mut tty2 = - daemon_proc.attach("sh1", Default::default()).context("attaching from tty2")?; - let mut line_matcher2 = tty2.stderr_line_matcher()?; - line_matcher2.scan_until_re("already has a terminal attached$")?; + let mut tty2 = daemon_proc.attach("sh1", Default::default()).context("attaching from tty2")?; + let mut line_matcher2 = tty2.stderr_line_matcher()?; + line_matcher2.scan_until_re("already has a terminal attached$")?; - Ok(()) - }) + Ok(()) } #[test] #[timeout(30000)] fn blank_session_not_allowed() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new( - "norc.toml", - DaemonArgs { listen_events: false, ..DaemonArgs::default() }, - ) - .context("starting daemon proc")?; + let mut daemon_proc = support::daemon::Proc::new( + "norc.toml", + DaemonArgs { listen_events: false, ..DaemonArgs::default() }, + ) + .context("starting daemon proc")?; - let mut tty1 = daemon_proc.attach("", Default::default()).context("attaching from tty1")?; - let mut line_matcher1 = tty1.stderr_line_matcher()?; - line_matcher1.scan_until_re("blank session names are not allowed")?; + let mut tty1 = daemon_proc.attach("", Default::default()).context("attaching from tty1")?; + let mut line_matcher1 = tty1.stderr_line_matcher()?; + line_matcher1.scan_until_re("blank session names are not allowed")?; - Ok(()) - }) + Ok(()) } #[test] #[timeout(30000)] fn whitespace_session_not_allowed() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new( - "norc.toml", - DaemonArgs { listen_events: false, ..DaemonArgs::default() }, - ) - .context("starting daemon proc")?; + let mut daemon_proc = support::daemon::Proc::new( + "norc.toml", + DaemonArgs { listen_events: false, ..DaemonArgs::default() }, + ) + .context("starting daemon proc")?; - let mut tty1 = - daemon_proc.attach("this\tbad", Default::default()).context("attaching from tty1")?; - let mut line_matcher1 = tty1.stderr_line_matcher()?; - line_matcher1.scan_until_re("whitespace is not allowed in session names")?; + let mut tty1 = + daemon_proc.attach("this\tbad", Default::default()).context("attaching from tty1")?; + let mut line_matcher1 = tty1.stderr_line_matcher()?; + line_matcher1.scan_until_re("whitespace is not allowed in session names")?; - Ok(()) - }) + Ok(()) } #[test] #[timeout(30000)] fn daemon_hangup() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new( - "norc.toml", - DaemonArgs { listen_events: false, ..DaemonArgs::default() }, - ) - .context("starting daemon proc")?; - let mut attach_proc = - daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; + let mut daemon_proc = support::daemon::Proc::new( + "norc.toml", + DaemonArgs { listen_events: false, ..DaemonArgs::default() }, + ) + .context("starting daemon proc")?; + let mut attach_proc = + daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; - // make sure the shell is up and running - let mut line_matcher = attach_proc.line_matcher()?; - attach_proc.run_cmd("echo foo")?; - line_matcher.scan_until_re("foo$")?; + // make sure the shell is up and running + let mut line_matcher = attach_proc.line_matcher()?; + attach_proc.run_cmd("echo foo")?; + line_matcher.scan_until_re("foo$")?; - daemon_proc.proc_kill()?; + daemon_proc.proc_kill()?; - let exit_status = attach_proc.proc.wait()?; - assert!(!exit_status.success()); + let exit_status = attach_proc.proc.wait()?; + assert!(!exit_status.success()); - Ok(()) - }) + Ok(()) } #[test] #[timeout(30000)] fn default_keybinding_detach() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) - .context("starting daemon proc")?; - let mut waiter = daemon_proc.events.take().unwrap().waiter(["daemon-bidi-stream-done"]); + let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) + .context("starting daemon proc")?; + let mut waiter = daemon_proc.events.take().unwrap().waiter(["daemon-bidi-stream-done"]); - let mut a1 = - daemon_proc.attach("sess", Default::default()).context("starting attach proc")?; - let mut lm1 = a1.line_matcher()?; + let mut a1 = daemon_proc.attach("sess", Default::default()).context("starting attach proc")?; + let mut lm1 = a1.line_matcher()?; - a1.run_cmd("export MYVAR=someval")?; - a1.run_cmd("echo $MYVAR")?; - lm1.scan_until_re("someval$")?; + a1.run_cmd("export MYVAR=someval")?; + a1.run_cmd("echo $MYVAR")?; + lm1.scan_until_re("someval$")?; - a1.run_raw_cmd(vec![0, 17])?; // Ctrl-Space Ctrl-q - let exit_status = a1.proc.wait()?; - assert!(exit_status.success()); + a1.run_raw_cmd(vec![0, 17])?; // Ctrl-Space Ctrl-q + let exit_status = a1.proc.wait()?; + assert!(exit_status.success()); - waiter.wait_event("daemon-bidi-stream-done")?; + waiter.wait_event("daemon-bidi-stream-done")?; - let mut a2 = - daemon_proc.attach("sess", Default::default()).context("starting attach proc 2")?; - let mut lm2 = a2.line_matcher()?; + let mut a2 = + daemon_proc.attach("sess", Default::default()).context("starting attach proc 2")?; + let mut lm2 = a2.line_matcher()?; - a2.run_cmd("echo $MYVAR")?; - lm2.scan_until_re("someval$")?; + a2.run_cmd("echo $MYVAR")?; + lm2.scan_until_re("someval$")?; - Ok(()) - }) + Ok(()) } // test to exercise the code path where a keybinding @@ -608,352 +564,319 @@ fn default_keybinding_detach() -> anyhow::Result<()> { #[test] #[timeout(30000)] fn keybinding_input_shear() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) - .context("starting daemon proc")?; - let mut waiter = daemon_proc.events.take().unwrap().waiter(["daemon-bidi-stream-done"]); + let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) + .context("starting daemon proc")?; + let mut waiter = daemon_proc.events.take().unwrap().waiter(["daemon-bidi-stream-done"]); - let mut a1 = - daemon_proc.attach("sess", Default::default()).context("starting attach proc")?; - let mut lm1 = a1.line_matcher()?; + let mut a1 = daemon_proc.attach("sess", Default::default()).context("starting attach proc")?; + let mut lm1 = a1.line_matcher()?; - a1.run_cmd("export MYVAR=someval")?; - a1.run_cmd("echo $MYVAR")?; - lm1.scan_until_re("someval$")?; + a1.run_cmd("export MYVAR=someval")?; + a1.run_cmd("echo $MYVAR")?; + lm1.scan_until_re("someval$")?; - a1.run_raw(vec![0])?; // Ctrl-Space - thread::sleep(time::Duration::from_millis(100)); - a1.run_raw(vec![17])?; // Ctrl-q - a1.proc.wait()?; + a1.run_raw(vec![0])?; // Ctrl-Space + thread::sleep(time::Duration::from_millis(100)); + a1.run_raw(vec![17])?; // Ctrl-q + a1.proc.wait()?; - waiter.wait_event("daemon-bidi-stream-done")?; + waiter.wait_event("daemon-bidi-stream-done")?; - let mut a2 = - daemon_proc.attach("sess", Default::default()).context("starting attach proc 2")?; - let mut lm2 = a2.line_matcher()?; + let mut a2 = + daemon_proc.attach("sess", Default::default()).context("starting attach proc 2")?; + let mut lm2 = a2.line_matcher()?; - a2.run_cmd("echo $MYVAR")?; - lm2.scan_until_re("someval$")?; + a2.run_cmd("echo $MYVAR")?; + lm2.scan_until_re("someval$")?; - Ok(()) - }) + Ok(()) } #[test] #[timeout(30000)] fn keybinding_strip_keys() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new( - "long_noop_keybinding.toml", - DaemonArgs { listen_events: false, ..DaemonArgs::default() }, - ) - .context("starting daemon proc")?; - let mut a1 = - daemon_proc.attach("sess", Default::default()).context("starting attach proc")?; - let mut lm1 = a1.line_matcher()?; + let mut daemon_proc = support::daemon::Proc::new( + "long_noop_keybinding.toml", + DaemonArgs { listen_events: false, ..DaemonArgs::default() }, + ) + .context("starting daemon proc")?; + let mut a1 = daemon_proc.attach("sess", Default::default()).context("starting attach proc")?; + let mut lm1 = a1.line_matcher()?; - // the keybinding is 5 'a' chars in a row, so they should get stripped out - a1.run_cmd("echo baaaaad")?; - lm1.scan_until_re("bd$")?; + // the keybinding is 5 'a' chars in a row, so they should get stripped out + a1.run_cmd("echo baaaaad")?; + lm1.scan_until_re("bd$")?; - Ok(()) - }) + Ok(()) } #[test] #[timeout(30000)] fn keybinding_strip_keys_split() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new( - "long_noop_keybinding.toml", - DaemonArgs { listen_events: false, ..DaemonArgs::default() }, - ) - .context("starting daemon proc")?; - let mut a1 = - daemon_proc.attach("sess", Default::default()).context("starting attach proc")?; - let mut lm1 = a1.line_matcher()?; - - // the keybinding is 5 'a' chars in a row, so they should get stripped out - a1.run_raw("echo ba".bytes().collect())?; - thread::sleep(time::Duration::from_millis(50)); - a1.run_raw("aa".bytes().collect())?; - thread::sleep(time::Duration::from_millis(50)); - a1.run_raw("aad\n".bytes().collect())?; - lm1.scan_until_re("bd")?; - - Ok(()) - }) + let mut daemon_proc = support::daemon::Proc::new( + "long_noop_keybinding.toml", + DaemonArgs { listen_events: false, ..DaemonArgs::default() }, + ) + .context("starting daemon proc")?; + let mut a1 = daemon_proc.attach("sess", Default::default()).context("starting attach proc")?; + let mut lm1 = a1.line_matcher()?; + + // the keybinding is 5 'a' chars in a row, so they should get stripped out + a1.run_raw("echo ba".bytes().collect())?; + thread::sleep(time::Duration::from_millis(50)); + a1.run_raw("aa".bytes().collect())?; + thread::sleep(time::Duration::from_millis(50)); + a1.run_raw("aad\n".bytes().collect())?; + lm1.scan_until_re("bd")?; + + Ok(()) } #[test] #[timeout(30000)] fn keybinding_partial_match_nostrip() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new( - "long_noop_keybinding.toml", - DaemonArgs { listen_events: false, ..DaemonArgs::default() }, - ) - .context("starting daemon proc")?; - let mut a1 = - daemon_proc.attach("sess", Default::default()).context("starting attach proc")?; - let mut lm1 = a1.line_matcher()?; + let mut daemon_proc = support::daemon::Proc::new( + "long_noop_keybinding.toml", + DaemonArgs { listen_events: false, ..DaemonArgs::default() }, + ) + .context("starting daemon proc")?; + let mut a1 = daemon_proc.attach("sess", Default::default()).context("starting attach proc")?; + let mut lm1 = a1.line_matcher()?; - // the keybinding is 5 'a' chars in a row, this has only 3 - a1.run_cmd("echo baaad")?; - lm1.scan_until_re("baaad$")?; + // the keybinding is 5 'a' chars in a row, this has only 3 + a1.run_cmd("echo baaad")?; + lm1.scan_until_re("baaad$")?; - Ok(()) - }) + Ok(()) } #[test] #[timeout(30000)] fn keybinding_partial_match_nostrip_split() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new( - "long_noop_keybinding.toml", - DaemonArgs { listen_events: false, ..DaemonArgs::default() }, - ) - .context("starting daemon proc")?; - let mut a1 = - daemon_proc.attach("sess", Default::default()).context("starting attach proc")?; - let mut lm1 = a1.line_matcher()?; - - // the keybinding is 5 'a' chars in a row, this has only 3 - a1.run_raw("echo ba".bytes().collect())?; - thread::sleep(time::Duration::from_millis(50)); - a1.run_raw("a".bytes().collect())?; - thread::sleep(time::Duration::from_millis(50)); - a1.run_raw("ad\n".bytes().collect())?; - lm1.scan_until_re("baaad$")?; - - Ok(()) - }) + let mut daemon_proc = support::daemon::Proc::new( + "long_noop_keybinding.toml", + DaemonArgs { listen_events: false, ..DaemonArgs::default() }, + ) + .context("starting daemon proc")?; + let mut a1 = daemon_proc.attach("sess", Default::default()).context("starting attach proc")?; + let mut lm1 = a1.line_matcher()?; + + // the keybinding is 5 'a' chars in a row, this has only 3 + a1.run_raw("echo ba".bytes().collect())?; + thread::sleep(time::Duration::from_millis(50)); + a1.run_raw("a".bytes().collect())?; + thread::sleep(time::Duration::from_millis(50)); + a1.run_raw("ad\n".bytes().collect())?; + lm1.scan_until_re("baaad$")?; + + Ok(()) } #[test] #[timeout(30000)] fn custom_keybinding_detach() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = - support::daemon::Proc::new("custom_detach_keybinding.toml", DaemonArgs::default()) - .context("starting daemon proc")?; - let mut waiter = daemon_proc.events.take().unwrap().waiter(["daemon-bidi-stream-done"]); + let mut daemon_proc = + support::daemon::Proc::new("custom_detach_keybinding.toml", DaemonArgs::default()) + .context("starting daemon proc")?; + let mut waiter = daemon_proc.events.take().unwrap().waiter(["daemon-bidi-stream-done"]); - let mut a1 = - daemon_proc.attach("sess", Default::default()).context("starting attach proc")?; - let mut lm1 = a1.line_matcher()?; + let mut a1 = daemon_proc.attach("sess", Default::default()).context("starting attach proc")?; + let mut lm1 = a1.line_matcher()?; - a1.run_cmd("export MYVAR=someval")?; - a1.run_cmd("echo $MYVAR")?; - lm1.scan_until_re("someval$")?; + a1.run_cmd("export MYVAR=someval")?; + a1.run_cmd("echo $MYVAR")?; + lm1.scan_until_re("someval$")?; - a1.run_raw_cmd(vec![22, 23, 7])?; // Ctrl-v Ctrl-w Ctrl-g - a1.proc.wait()?; + a1.run_raw_cmd(vec![22, 23, 7])?; // Ctrl-v Ctrl-w Ctrl-g + a1.proc.wait()?; - waiter.wait_event("daemon-bidi-stream-done")?; + waiter.wait_event("daemon-bidi-stream-done")?; - let mut a2 = - daemon_proc.attach("sess", Default::default()).context("starting attach proc 2")?; - let mut lm2 = a2.line_matcher()?; + let mut a2 = + daemon_proc.attach("sess", Default::default()).context("starting attach proc 2")?; + let mut lm2 = a2.line_matcher()?; - a2.run_cmd("echo $MYVAR")?; - lm2.match_re("someval$")?; + a2.run_cmd("echo $MYVAR")?; + lm2.match_re("someval$")?; - Ok(()) - }) + Ok(()) } #[test] #[timeout(30000)] fn injects_term_even_with_env_config() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new("user_env.toml", DaemonArgs::default()) - .context("starting daemon proc")?; - let mut waiter = daemon_proc.events.take().unwrap().waiter(["daemon-wrote-s2c-chunk"]); + let mut daemon_proc = support::daemon::Proc::new("user_env.toml", DaemonArgs::default()) + .context("starting daemon proc")?; + let mut waiter = daemon_proc.events.take().unwrap().waiter(["daemon-wrote-s2c-chunk"]); - let mut attach_proc = daemon_proc - .attach( - "sh1", - AttachArgs { - extra_env: vec![(String::from("TERM"), String::from("dumb"))], - ..Default::default() - }, - ) - .context("starting attach proc")?; + let mut attach_proc = daemon_proc + .attach( + "sh1", + AttachArgs { + extra_env: vec![(String::from("TERM"), String::from("dumb"))], + ..Default::default() + }, + ) + .context("starting attach proc")?; - let mut line_matcher = attach_proc.line_matcher()?; + let mut line_matcher = attach_proc.line_matcher()?; - waiter.wait_event("daemon-wrote-s2c-chunk")?; // resize prompt redraw - attach_proc.run_cmd("echo $SOME_CUSTOM_ENV_VAR")?; - line_matcher.scan_until_re("customvalue$")?; + waiter.wait_event("daemon-wrote-s2c-chunk")?; // resize prompt redraw + attach_proc.run_cmd("echo $SOME_CUSTOM_ENV_VAR")?; + line_matcher.scan_until_re("customvalue$")?; - attach_proc.run_cmd("echo $TERM")?; - line_matcher.match_re("dumb$")?; + attach_proc.run_cmd("echo $TERM")?; + line_matcher.match_re("dumb$")?; - Ok(()) - }) + Ok(()) } #[test] #[timeout(30000)] fn injects_local_env_vars() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) - .context("starting daemon proc")?; - let mut attach_proc = daemon_proc - .attach( - "sh1", - AttachArgs { - extra_env: vec![ - (String::from("DISPLAY"), String::from(":0")), - (String::from("LANG"), String::from("fakelang")), - ], - ..Default::default() - }, - ) - .context("starting attach proc")?; - let mut line_matcher = attach_proc.line_matcher()?; + let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) + .context("starting daemon proc")?; + let mut attach_proc = daemon_proc + .attach( + "sh1", + AttachArgs { + extra_env: vec![ + (String::from("DISPLAY"), String::from(":0")), + (String::from("LANG"), String::from("fakelang")), + ], + ..Default::default() + }, + ) + .context("starting attach proc")?; + let mut line_matcher = attach_proc.line_matcher()?; - attach_proc.run_cmd("echo $DISPLAY")?; - line_matcher.scan_until_re(":0$")?; + attach_proc.run_cmd("echo $DISPLAY")?; + line_matcher.scan_until_re(":0$")?; - attach_proc.run_cmd("echo $LANG")?; - line_matcher.scan_until_re("fakelang$")?; + attach_proc.run_cmd("echo $LANG")?; + line_matcher.scan_until_re("fakelang$")?; - Ok(()) - }) + Ok(()) } #[test] #[timeout(30000)] fn has_right_default_path() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = - support::daemon::Proc::new("no_etc_environment.toml", DaemonArgs::default()) - .context("starting daemon proc")?; - let mut attach_proc = - daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; + let mut daemon_proc = + support::daemon::Proc::new("no_etc_environment.toml", DaemonArgs::default()) + .context("starting daemon proc")?; + let mut attach_proc = + daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; - let mut line_matcher = attach_proc.line_matcher()?; + let mut line_matcher = attach_proc.line_matcher()?; - attach_proc.run_cmd("echo $PATH")?; - line_matcher.scan_until_re("/usr/bin:/bin:/usr/sbin:/sbin$")?; + attach_proc.run_cmd("echo $PATH")?; + line_matcher.scan_until_re("/usr/bin:/bin:/usr/sbin:/sbin$")?; - Ok(()) - }) + Ok(()) } #[test] #[timeout(30000)] fn screen_restore() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = - support::daemon::Proc::new("restore_screen.toml", DaemonArgs::default()) - .context("starting daemon proc")?; - let bidi_done_w = daemon_proc.events.take().unwrap().waiter(["daemon-bidi-stream-done"]); - - { - let mut attach_proc = - daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; - let mut line_matcher = attach_proc.line_matcher()?; - - attach_proc.run_cmd("echo foo")?; - line_matcher.scan_until_re("foo$")?; - } - - // wait until the daemon has noticed that the connection - // has dropped before we attempt to open the connection again - daemon_proc.events = Some(bidi_done_w.wait_final_event("daemon-bidi-stream-done")?); + let mut daemon_proc = support::daemon::Proc::new("restore_screen.toml", DaemonArgs::default()) + .context("starting daemon proc")?; + let bidi_done_w = daemon_proc.events.take().unwrap().waiter(["daemon-bidi-stream-done"]); - { - let mut attach_proc = - daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; - let mut line_matcher = attach_proc.line_matcher()?; - line_matcher.never_matches("^.*SHPOOL_PROMPT_SETUP_SENTINEL.*$")?; + { + let mut attach_proc = + daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; + let mut line_matcher = attach_proc.line_matcher()?; - // the re-attach should redraw the screen for us, so we should - // get a line with "foo" as part of the re-drawn screen. - line_matcher.scan_until_re("foo$")?; + attach_proc.run_cmd("echo foo")?; + line_matcher.scan_until_re("foo$")?; + } + + // wait until the daemon has noticed that the connection + // has dropped before we attempt to open the connection again + daemon_proc.events = Some(bidi_done_w.wait_final_event("daemon-bidi-stream-done")?); + + { + let mut attach_proc = + daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; + let mut line_matcher = attach_proc.line_matcher()?; + line_matcher.never_matches("^.*SHPOOL_PROMPT_SETUP_SENTINEL.*$")?; - attach_proc.proc.kill()?; - } + // the re-attach should redraw the screen for us, so we should + // get a line with "foo" as part of the re-drawn screen. + line_matcher.scan_until_re("foo$")?; - Ok(()) - }) + attach_proc.proc.kill()?; + } + + Ok(()) } #[test] #[timeout(30000)] fn screen_wide_restore() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = - support::daemon::Proc::new("restore_screen.toml", DaemonArgs::default()) - .context("starting daemon proc")?; - let bidi_done_w = daemon_proc.events.take().unwrap().waiter(["daemon-bidi-stream-done"]); - - { - let mut attach_proc = - daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; - let mut line_matcher = attach_proc.line_matcher()?; - - attach_proc.run_cmd("echo ooooxooooyooooxooooyooooxooooyooooxooooyooooxooooyooooxooooyooooxooooyooooxooooyooooxooooyooooxooooy")?; - line_matcher.scan_until_re("ooooxooooyooooxooooyooooxooooyooooxooooyooooxooooyooooxooooyooooxooooyooooxooooyooooxooooyooooxooooy$")?; - } - - // wait until the daemon has noticed that the connection - // has dropped before we attempt to open the connection again - daemon_proc.events = Some(bidi_done_w.wait_final_event("daemon-bidi-stream-done")?); + let mut daemon_proc = support::daemon::Proc::new("restore_screen.toml", DaemonArgs::default()) + .context("starting daemon proc")?; + let bidi_done_w = daemon_proc.events.take().unwrap().waiter(["daemon-bidi-stream-done"]); - { - let mut attach_proc = - daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; - let mut line_matcher = attach_proc.line_matcher()?; + { + let mut attach_proc = + daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; + let mut line_matcher = attach_proc.line_matcher()?; + + attach_proc.run_cmd("echo ooooxooooyooooxooooyooooxooooyooooxooooyooooxooooyooooxooooyooooxooooyooooxooooyooooxooooyooooxooooy")?; + line_matcher.scan_until_re("ooooxooooyooooxooooyooooxooooyooooxooooyooooxooooyooooxooooyooooxooooyooooxooooyooooxooooyooooxooooy$")?; + } - // the re-attach should redraw the screen for us, so we should - // get a line with the full echo result as part of the re-drawn screen. - line_matcher.scan_until_re("ooooxooooyooooxooooyooooxooooyooooxooooyooooxooooyooooxooooyooooxooooyooooxooooyooooxooooyooooxooooy$")?; - } + // wait until the daemon has noticed that the connection + // has dropped before we attempt to open the connection again + daemon_proc.events = Some(bidi_done_w.wait_final_event("daemon-bidi-stream-done")?); - Ok(()) - }) + { + let mut attach_proc = + daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; + let mut line_matcher = attach_proc.line_matcher()?; + + // the re-attach should redraw the screen for us, so we should + // get a line with the full echo result as part of the re-drawn screen. + line_matcher.scan_until_re("ooooxooooyooooxooooyooooxooooyooooxooooyooooxooooyooooxooooyooooxooooyooooxooooyooooxooooyooooxooooy$")?; + } + + Ok(()) } #[test] #[timeout(30000)] fn lines_restore() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = - support::daemon::Proc::new("restore_lines.toml", DaemonArgs::default()) - .context("starting daemon proc")?; - let bidi_done_w = daemon_proc.events.take().unwrap().waiter(["daemon-bidi-stream-done"]); - - { - let mut attach_proc = - daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; - let mut line_matcher = attach_proc.line_matcher()?; - - attach_proc.run_cmd("echo foo")?; - attach_proc.run_cmd("echo")?; - line_matcher.scan_until_re("foo$")?; - } - - // wait until the daemon has noticed that the connection - // has dropped before we attempt to open the connection again - daemon_proc.events = Some(bidi_done_w.wait_final_event("daemon-bidi-stream-done")?); + let mut daemon_proc = support::daemon::Proc::new("restore_lines.toml", DaemonArgs::default()) + .context("starting daemon proc")?; + let bidi_done_w = daemon_proc.events.take().unwrap().waiter(["daemon-bidi-stream-done"]); - { - let mut attach_proc = - daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; - let mut line_matcher = attach_proc.line_matcher()?; + { + let mut attach_proc = + daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; + let mut line_matcher = attach_proc.line_matcher()?; - // the re-attach should redraw the last 2 lines for us, so we should - // get a line with "foo" as part of the re-drawn screen. - line_matcher.scan_until_re("foo$")?; - } + attach_proc.run_cmd("echo foo")?; + attach_proc.run_cmd("echo")?; + line_matcher.scan_until_re("foo$")?; + } + + // wait until the daemon has noticed that the connection + // has dropped before we attempt to open the connection again + daemon_proc.events = Some(bidi_done_w.wait_final_event("daemon-bidi-stream-done")?); + + { + let mut attach_proc = + daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; + let mut line_matcher = attach_proc.line_matcher()?; + + // the re-attach should redraw the last 2 lines for us, so we should + // get a line with "foo" as part of the re-drawn screen. + line_matcher.scan_until_re("foo$")?; + } - Ok(()) - }) + Ok(()) } // Test to make sure that when we do a restore, we don't send back too many @@ -962,221 +885,204 @@ fn lines_restore() -> anyhow::Result<()> { #[test] #[timeout(30000)] fn lines_big_chunk_restore() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = - support::daemon::Proc::new("restore_many_lines.toml", DaemonArgs::default()) - .context("starting daemon proc")?; - let mut waiter = daemon_proc - .events - .take() - .unwrap() - .waiter(["daemon-wrote-s2c-chunk", "daemon-bidi-stream-done"]); - - // BUF_SIZE from src/consts.rs - let max_chunk_size = 1024 * 16; - - { - let mut attach_proc = - daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; - let mut line_matcher = attach_proc.line_matcher()?; - - // wait for shell output to avoid racing against the shell - waiter.wait_event("daemon-wrote-s2c-chunk")?; - - // generate a bunch of data that will cause the restore buffer to be too large - // for a single chunk - let blob = format!("echo {}", (0..max_chunk_size).map(|_| "x").collect::()); - attach_proc.run_cmd(blob.as_str())?; - line_matcher.scan_until_re("xx$")?; - - attach_proc.run_cmd("echo food")?; - line_matcher.match_re("food$")?; - } - - // wait until the daemon has noticed that the connection - // has dropped before we attempt to open the connection again - daemon_proc.events = Some(waiter.wait_final_event("daemon-bidi-stream-done")?); - - { - let mut attach_proc = - daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; - let mut reader = std::io::BufReader::new( - attach_proc.proc.stdout.take().ok_or(anyhow!("missing stdout"))?, - ); - - let mut output = vec![]; - reader.read_until(b'd', &mut output)?; - let chunk = String::from_utf8_lossy(&output[..]); - assert!(chunk.contains("foo")); - } - - Ok(()) - }) + let mut daemon_proc = + support::daemon::Proc::new("restore_many_lines.toml", DaemonArgs::default()) + .context("starting daemon proc")?; + let mut waiter = daemon_proc + .events + .take() + .unwrap() + .waiter(["daemon-wrote-s2c-chunk", "daemon-bidi-stream-done"]); + + // BUF_SIZE from src/consts.rs + let max_chunk_size = 1024 * 16; + + { + let mut attach_proc = + daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; + let mut line_matcher = attach_proc.line_matcher()?; + + // wait for shell output to avoid racing against the shell + waiter.wait_event("daemon-wrote-s2c-chunk")?; + + // generate a bunch of data that will cause the restore buffer to be too large + // for a single chunk + let blob = format!("echo {}", (0..max_chunk_size).map(|_| "x").collect::()); + attach_proc.run_cmd(blob.as_str())?; + line_matcher.scan_until_re("xx$")?; + + attach_proc.run_cmd("echo food")?; + line_matcher.match_re("food$")?; + } + + // wait until the daemon has noticed that the connection + // has dropped before we attempt to open the connection again + daemon_proc.events = Some(waiter.wait_final_event("daemon-bidi-stream-done")?); + + { + let mut attach_proc = + daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; + let mut reader = std::io::BufReader::new( + attach_proc.proc.stdout.take().ok_or(anyhow!("missing stdout"))?, + ); + + let mut output = vec![]; + reader.read_until(b'd', &mut output)?; + let chunk = String::from_utf8_lossy(&output[..]); + assert!(chunk.contains("foo")); + } + + Ok(()) } #[test] #[timeout(30000)] fn exits_with_same_status_as_shell() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) - .context("starting daemon proc")?; - let mut attach_proc = - daemon_proc.attach("sh", Default::default()).context("starting attach proc")?; - - attach_proc.run_cmd("exit 19")?; - - assert_eq!( - attach_proc - .proc - .wait() - .context("waiting for attach proc to exit")? - .code() - .ok_or(anyhow!("no exit code"))?, - 19 - ); + let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) + .context("starting daemon proc")?; + let mut attach_proc = + daemon_proc.attach("sh", Default::default()).context("starting attach proc")?; + + attach_proc.run_cmd("exit 19")?; - Ok(()) - }) + assert_eq!( + attach_proc + .proc + .wait() + .context("waiting for attach proc to exit")? + .code() + .ok_or(anyhow!("no exit code"))?, + 19 + ); + + Ok(()) } #[test] #[timeout(30000)] fn ttl_hangup() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) - .context("starting daemon proc")?; - let mut attach_proc = daemon_proc - .attach( - "sh1", - AttachArgs { ttl: Some(time::Duration::from_secs(1)), ..Default::default() }, - ) - .context("starting attach proc")?; + let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) + .context("starting daemon proc")?; + let mut attach_proc = daemon_proc + .attach("sh1", AttachArgs { ttl: Some(time::Duration::from_secs(1)), ..Default::default() }) + .context("starting attach proc")?; - // ensure the shell is up and running - let mut line_matcher = attach_proc.line_matcher()?; - attach_proc.run_cmd("echo hi")?; - line_matcher.scan_until_re("hi$")?; + // ensure the shell is up and running + let mut line_matcher = attach_proc.line_matcher()?; + attach_proc.run_cmd("echo hi")?; + line_matcher.scan_until_re("hi$")?; - // sleep long enough for the reaper to clobber the thread - thread::sleep(time::Duration::from_millis(1200)); + // sleep long enough for the reaper to clobber the thread + thread::sleep(time::Duration::from_millis(1200)); - let listout = daemon_proc.list()?; - assert!(!String::from_utf8_lossy(listout.stdout.as_slice()).contains("sh1")); + let listout = daemon_proc.list()?; + assert!(!String::from_utf8_lossy(listout.stdout.as_slice()).contains("sh1")); - Ok(()) - }) + Ok(()) } #[test] #[timeout(30000)] fn ttl_no_hangup_yet() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) - .context("starting daemon proc")?; - let mut attach_proc = daemon_proc - .attach( - "sh1", - AttachArgs { ttl: Some(time::Duration::from_secs(1000)), ..Default::default() }, - ) - .context("starting attach proc")?; + let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) + .context("starting daemon proc")?; + let mut attach_proc = daemon_proc + .attach( + "sh1", + AttachArgs { ttl: Some(time::Duration::from_secs(1000)), ..Default::default() }, + ) + .context("starting attach proc")?; - // ensure the shell is up and running - let mut line_matcher = attach_proc.line_matcher()?; - attach_proc.run_cmd("echo hi")?; - line_matcher.scan_until_re("hi$")?; + // ensure the shell is up and running + let mut line_matcher = attach_proc.line_matcher()?; + attach_proc.run_cmd("echo hi")?; + line_matcher.scan_until_re("hi$")?; - let listout = daemon_proc.list()?; - assert!(String::from_utf8_lossy(listout.stdout.as_slice()).contains("sh1")); + let listout = daemon_proc.list()?; + assert!(String::from_utf8_lossy(listout.stdout.as_slice()).contains("sh1")); - Ok(()) - }) + Ok(()) } #[test] #[timeout(30000)] fn prompt_prefix_bash() -> anyhow::Result<()> { - support::dump_err(|| { - let daemon_proc = - support::daemon::Proc::new("prompt_prefix_bash.toml", DaemonArgs::default()) - .context("starting daemon proc")?; - - // we have to manually spawn the child proc rather than using the support - // util because the line matcher gets bound only after the process gets - // spawned, so there will be a race between the prompt printing and - // binding the line matcher if we use the wrapper util. - let mut child = Command::new(support::shpool_bin()?) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .arg("--socket") - .arg(&daemon_proc.socket_path) - .arg("--config-file") - .arg(support::testdata_file("prompt_prefix_bash.toml")) - .arg("attach") - .arg("sh1") - .spawn() - .context("spawning attach process")?; - - // The attach shell should be spawned and have read the - // initial prompt after half a second. - std::thread::sleep(time::Duration::from_millis(500)); - child.kill().context("killing child")?; - - let mut stderr = child.stderr.take().context("missing stderr")?; - let mut stderr_str = String::from(""); - stderr.read_to_string(&mut stderr_str).context("slurping stderr")?; - assert!(stderr_str.is_empty()); - - let mut stdout = child.stdout.take().context("missing stdout")?; - let mut stdout_str = String::from(""); - stdout.read_to_string(&mut stdout_str).context("slurping stdout")?; - eprintln!("stdout_str: {}", stdout_str); - let stdout_re = Regex::new(".*session_name=sh1 prompt>.*")?; - assert!(stdout_re.is_match(&stdout_str)); - - Ok(()) - }) + let daemon_proc = support::daemon::Proc::new("prompt_prefix_bash.toml", DaemonArgs::default()) + .context("starting daemon proc")?; + + // we have to manually spawn the child proc rather than using the support + // util because the line matcher gets bound only after the process gets + // spawned, so there will be a race between the prompt printing and + // binding the line matcher if we use the wrapper util. + let mut child = Command::new(support::shpool_bin()?) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .arg("--socket") + .arg(&daemon_proc.socket_path) + .arg("--config-file") + .arg(support::testdata_file("prompt_prefix_bash.toml")) + .arg("attach") + .arg("sh1") + .spawn() + .context("spawning attach process")?; + + // The attach shell should be spawned and have read the + // initial prompt after half a second. + std::thread::sleep(time::Duration::from_millis(500)); + child.kill().context("killing child")?; + + let mut stderr = child.stderr.take().context("missing stderr")?; + let mut stderr_str = String::from(""); + stderr.read_to_string(&mut stderr_str).context("slurping stderr")?; + assert!(stderr_str.is_empty()); + + let mut stdout = child.stdout.take().context("missing stdout")?; + let mut stdout_str = String::from(""); + stdout.read_to_string(&mut stdout_str).context("slurping stdout")?; + eprintln!("stdout_str: {}", stdout_str); + let stdout_re = Regex::new(".*session_name=sh1 prompt>.*")?; + assert!(stdout_re.is_match(&stdout_str)); + + Ok(()) } #[test] #[timeout(30000)] #[cfg_attr(target_os = "macos", ignore)] // hard-coded /usr/bin/zsh path fn prompt_prefix_zsh() -> anyhow::Result<()> { - support::dump_err(|| { - let daemon_proc = - support::daemon::Proc::new("prompt_prefix_zsh.toml", DaemonArgs::default()) - .context("starting daemon proc")?; - - // see the bash case for why - let mut child = Command::new(support::shpool_bin()?) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .arg("--socket") - .arg(&daemon_proc.socket_path) - .arg("--config-file") - .arg(support::testdata_file("prompt_prefix_zsh.toml")) - .arg("attach") - .arg("sh1") - .spawn() - .context("spawning attach process")?; - - // The attach shell should be spawned and have read the - // initial prompt after half a second. - std::thread::sleep(time::Duration::from_millis(500)); - child.kill().context("killing child")?; - - let mut stderr = child.stderr.take().context("missing stderr")?; - let mut stderr_str = String::from(""); - stderr.read_to_string(&mut stderr_str).context("slurping stderr")?; - assert!(stderr_str.is_empty()); - - let mut stdout = child.stdout.take().context("missing stdout")?; - let mut stdout_str = String::from(""); - stdout.read_to_string(&mut stdout_str).context("slurping stdout")?; - let stdout_re = Regex::new(".*session_name=sh1.*")?; - assert!(stdout_re.is_match(&stdout_str)); - - Ok(()) - }) + let daemon_proc = support::daemon::Proc::new("prompt_prefix_zsh.toml", DaemonArgs::default()) + .context("starting daemon proc")?; + + // see the bash case for why + let mut child = Command::new(support::shpool_bin()?) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .arg("--socket") + .arg(&daemon_proc.socket_path) + .arg("--config-file") + .arg(support::testdata_file("prompt_prefix_zsh.toml")) + .arg("attach") + .arg("sh1") + .spawn() + .context("spawning attach process")?; + + // The attach shell should be spawned and have read the + // initial prompt after half a second. + std::thread::sleep(time::Duration::from_millis(500)); + child.kill().context("killing child")?; + + let mut stderr = child.stderr.take().context("missing stderr")?; + let mut stderr_str = String::from(""); + stderr.read_to_string(&mut stderr_str).context("slurping stderr")?; + assert!(stderr_str.is_empty()); + + let mut stdout = child.stdout.take().context("missing stdout")?; + let mut stdout_str = String::from(""); + stdout.read_to_string(&mut stdout_str).context("slurping stdout")?; + let stdout_re = Regex::new(".*session_name=sh1.*")?; + assert!(stdout_re.is_match(&stdout_str)); + + Ok(()) } // This has stopped working in CI. Probably due to a fish version @@ -1185,75 +1091,70 @@ fn prompt_prefix_zsh() -> anyhow::Result<()> { #[timeout(30000)] #[cfg_attr(target_os = "macos", ignore)] // hard-coded /usr/bin/fish path fn prompt_prefix_fish() -> anyhow::Result<()> { - support::dump_err(|| { - let daemon_proc = - support::daemon::Proc::new("prompt_prefix_fish.toml", DaemonArgs::default()) - .context("starting daemon proc")?; - - // see the bash case for why - let mut child = Command::new(support::shpool_bin()?) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .arg("--socket") - .arg(&daemon_proc.socket_path) - .arg("--config-file") - .arg(support::testdata_file("prompt_prefix_fish.toml")) - .arg("attach") - .arg("sh1") - .spawn() - .context("spawning attach process")?; - - // The attach shell should be spawned and have read the - // initial prompt after half a second. - std::thread::sleep(time::Duration::from_millis(500)); - child.kill().context("killing child")?; - - let mut stderr = child.stderr.take().context("missing stderr")?; - let mut stderr_str = String::from(""); - stderr.read_to_string(&mut stderr_str).context("slurping stderr")?; - assert!(stderr_str.is_empty()); - - let mut stdout = child.stdout.take().context("missing stdout")?; - let mut stdout_str = String::from(""); - stdout.read_to_string(&mut stdout_str).context("slurping stdout")?; - let stdout_re = Regex::new(".*session_name=sh1.*")?; - assert!(stdout_re.is_match(&stdout_str)); - - Ok(()) - }) + let daemon_proc = support::daemon::Proc::new("prompt_prefix_fish.toml", DaemonArgs::default()) + .context("starting daemon proc")?; + + // see the bash case for why + let mut child = Command::new(support::shpool_bin()?) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .arg("--socket") + .arg(&daemon_proc.socket_path) + .arg("--config-file") + .arg(support::testdata_file("prompt_prefix_fish.toml")) + .arg("attach") + .arg("sh1") + .spawn() + .context("spawning attach process")?; + + // The attach shell should be spawned and have read the + // initial prompt after half a second. + std::thread::sleep(time::Duration::from_millis(500)); + child.kill().context("killing child")?; + + let mut stderr = child.stderr.take().context("missing stderr")?; + let mut stderr_str = String::from(""); + stderr.read_to_string(&mut stderr_str).context("slurping stderr")?; + assert!(stderr_str.is_empty()); + + let mut stdout = child.stdout.take().context("missing stdout")?; + let mut stdout_str = String::from(""); + stdout.read_to_string(&mut stdout_str).context("slurping stdout")?; + let stdout_re = Regex::new(".*session_name=sh1.*")?; + assert!(stdout_re.is_match(&stdout_str)); + + Ok(()) } #[test] #[timeout(30000)] fn motd_dump() -> anyhow::Result<()> { - support::dump_err(|| { - // set up the config - let tmp_dir = tmpdir::Dir::new("/tmp/shpool-test")?; - eprintln!("building config in {:?}", tmp_dir.path()); - let motd_file = tmp_dir.path().join("motd.txt"); - { - let mut f = fs::File::create(&motd_file)?; - f.write_all("MOTD_MSG".as_bytes())?; - } - let config_tmpl = fs::read_to_string(support::testdata_file("motd_dump.toml.tmpl"))?; - let config_contents = config_tmpl.replace("TMP_MOTD_MSG_FILE", motd_file.to_str().unwrap()); - let config_file = tmp_dir.path().join("motd_dump.toml"); - { - let mut f = fs::File::create(&config_file)?; - f.write_all(config_contents.as_bytes())?; - } - - // spawn a daemon based on our custom config - let mut daemon_proc = support::daemon::Proc::new(&config_file, DaemonArgs::default()) - .context("starting daemon proc")?; + // set up the config + let tmp_dir = tmpdir::Dir::new("/tmp/shpool-test")?; + eprintln!("building config in {:?}", tmp_dir.path()); + let motd_file = tmp_dir.path().join("motd.txt"); + { + let mut f = fs::File::create(&motd_file)?; + f.write_all("MOTD_MSG".as_bytes())?; + } + let config_tmpl = fs::read_to_string(support::testdata_file("motd_dump.toml.tmpl"))?; + let config_contents = config_tmpl.replace("TMP_MOTD_MSG_FILE", motd_file.to_str().unwrap()); + let config_file = tmp_dir.path().join("motd_dump.toml"); + { + let mut f = fs::File::create(&config_file)?; + f.write_all(config_contents.as_bytes())?; + } - let mut attach_proc = - daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; - let mut line_matcher = attach_proc.line_matcher()?; - line_matcher.scan_until_re(".*MOTD_MSG.*")?; + // spawn a daemon based on our custom config + let mut daemon_proc = support::daemon::Proc::new(&config_file, DaemonArgs::default()) + .context("starting daemon proc")?; - Ok(()) - }) + let mut attach_proc = + daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; + let mut line_matcher = attach_proc.line_matcher()?; + line_matcher.scan_until_re(".*MOTD_MSG.*")?; + + Ok(()) } /// Attach to the given daemon and wait for the given duration, then @@ -1298,401 +1199,372 @@ fn snapshot_attach_output>( #[timeout(30000)] #[cfg_attr(target_os = "macos", ignore)] // pager pty output issue fn motd_pager() -> anyhow::Result<()> { - support::dump_err(|| { - // set up the config - let tmp_dir = tmpdir::Dir::new("/tmp/shpool-test")?; - eprintln!("building config in {:?}", tmp_dir.path()); - let motd_file = tmp_dir.path().join("motd.txt"); - { - let mut f = fs::File::create(&motd_file)?; - f.write_all("MOTD_MSG\n".as_bytes())?; - } - let config_file = tmp_dir.path().join("motd_pager.toml"); - - // spawn a daemon based on our custom config - let mut daemon_proc = support::daemon::Proc::new( - &config_file, - DaemonArgs { - extra_env: vec![(String::from("TERM"), String::from("xterm"))], - ..DaemonArgs::default() - }, - ) - .context("starting daemon proc")?; + // set up the config + let tmp_dir = tmpdir::Dir::new("/tmp/shpool-test")?; + eprintln!("building config in {:?}", tmp_dir.path()); + let motd_file = tmp_dir.path().join("motd.txt"); + { + let mut f = fs::File::create(&motd_file)?; + f.write_all("MOTD_MSG\n".as_bytes())?; + } + let config_file = tmp_dir.path().join("motd_pager.toml"); - // Update the config and wait for it to get picked up. - // Doing this after the daemon starts tests to make sure - // that we can handle dynamic config changes to the - // motd settings. - let config_tmpl = fs::read_to_string(support::testdata_file("motd_pager.toml.tmpl"))?; - let config_contents = config_tmpl.replace("TMP_MOTD_MSG_FILE", motd_file.to_str().unwrap()); - { - let mut f = fs::File::create(&config_file)?; - f.write_all(config_contents.as_bytes())?; - } - daemon_proc.await_event("daemon-reload-config")?; - - let stdout_str = snapshot_attach_output( - &daemon_proc, - &config_file, - time::Duration::from_millis(500), - "sh1", - )?; - // Scan for a fragment of less output. - let stdout_file_re = Regex::new(".*\\(END\\).*")?; - assert!(stdout_file_re.is_match(&stdout_str)); + // spawn a daemon based on our custom config + let mut daemon_proc = support::daemon::Proc::new( + &config_file, + DaemonArgs { + extra_env: vec![(String::from("TERM"), String::from("xterm"))], + ..DaemonArgs::default() + }, + ) + .context("starting daemon proc")?; - Ok(()) - }) + // Update the config and wait for it to get picked up. + // Doing this after the daemon starts tests to make sure + // that we can handle dynamic config changes to the + // motd settings. + let config_tmpl = fs::read_to_string(support::testdata_file("motd_pager.toml.tmpl"))?; + let config_contents = config_tmpl.replace("TMP_MOTD_MSG_FILE", motd_file.to_str().unwrap()); + { + let mut f = fs::File::create(&config_file)?; + f.write_all(config_contents.as_bytes())?; + } + daemon_proc.await_event("daemon-reload-config")?; + + let stdout_str = snapshot_attach_output( + &daemon_proc, + &config_file, + time::Duration::from_millis(500), + "sh1", + )?; + // Scan for a fragment of less output. + let stdout_file_re = Regex::new(".*\\(END\\).*")?; + assert!(stdout_file_re.is_match(&stdout_str)); + + Ok(()) } #[test] #[timeout(30000)] #[cfg_attr(target_os = "macos", ignore)] // pager pty output issue fn motd_debounced_pager_debounces() -> anyhow::Result<()> { - support::dump_err(|| { - // set up the config - let tmp_dir = tmpdir::Dir::new("/tmp/shpool-test")?; - eprintln!("building config in {:?}", tmp_dir.path()); - let motd_file = tmp_dir.path().join("motd.txt"); - { - let mut f = fs::File::create(&motd_file)?; - f.write_all("MOTD_MSG\n".as_bytes())?; - } - let config_tmpl = - fs::read_to_string(support::testdata_file("motd_pager_1d_debounce.toml.tmpl"))?; - let config_contents = config_tmpl.replace("TMP_MOTD_MSG_FILE", motd_file.to_str().unwrap()); - let config_file = tmp_dir.path().join("motd_pager.toml"); - { - let mut f = fs::File::create(&config_file)?; - f.write_all(config_contents.as_bytes())?; - } - - // spawn a daemon based on our custom config - let daemon_proc = support::daemon::Proc::new( - &config_file, - DaemonArgs { - extra_env: vec![(String::from("TERM"), String::from("xterm"))], - ..DaemonArgs::default() - }, - ) - .context("starting daemon proc")?; + // set up the config + let tmp_dir = tmpdir::Dir::new("/tmp/shpool-test")?; + eprintln!("building config in {:?}", tmp_dir.path()); + let motd_file = tmp_dir.path().join("motd.txt"); + { + let mut f = fs::File::create(&motd_file)?; + f.write_all("MOTD_MSG\n".as_bytes())?; + } + let config_tmpl = + fs::read_to_string(support::testdata_file("motd_pager_1d_debounce.toml.tmpl"))?; + let config_contents = config_tmpl.replace("TMP_MOTD_MSG_FILE", motd_file.to_str().unwrap()); + let config_file = tmp_dir.path().join("motd_pager.toml"); + { + let mut f = fs::File::create(&config_file)?; + f.write_all(config_contents.as_bytes())?; + } - let stdout_str = snapshot_attach_output( - &daemon_proc, - &config_file, - time::Duration::from_millis(500), - "sh1", - )?; - // scan for a fragment of less output - let stdout_file_re = Regex::new(".*\\(END\\).*")?; - assert!(stdout_file_re.is_match(&stdout_str)); - - // We should see not the message again when we try again immediately. - let stdout_str = snapshot_attach_output( - &daemon_proc, - &config_file, - time::Duration::from_millis(500), - "sh2", - )?; - assert!(!stdout_file_re.is_match(&stdout_str)); - - Ok(()) - }) + // spawn a daemon based on our custom config + let daemon_proc = support::daemon::Proc::new( + &config_file, + DaemonArgs { + extra_env: vec![(String::from("TERM"), String::from("xterm"))], + ..DaemonArgs::default() + }, + ) + .context("starting daemon proc")?; + + let stdout_str = snapshot_attach_output( + &daemon_proc, + &config_file, + time::Duration::from_millis(500), + "sh1", + )?; + // scan for a fragment of less output + let stdout_file_re = Regex::new(".*\\(END\\).*")?; + assert!(stdout_file_re.is_match(&stdout_str)); + + // We should see not the message again when we try again immediately. + let stdout_str = snapshot_attach_output( + &daemon_proc, + &config_file, + time::Duration::from_millis(500), + "sh2", + )?; + assert!(!stdout_file_re.is_match(&stdout_str)); + + Ok(()) } #[test] #[timeout(30000)] #[cfg_attr(target_os = "macos", ignore)] // pager pty output issue fn motd_debounced_pager_unbounces() -> anyhow::Result<()> { - support::dump_err(|| { - // set up the config - let tmp_dir = tmpdir::Dir::new("/tmp/shpool-test")?; - eprintln!("building config in {:?}", tmp_dir.path()); - let motd_file = tmp_dir.path().join("motd.txt"); - { - let mut f = fs::File::create(&motd_file)?; - f.write_all("MOTD_MSG\n".as_bytes())?; - } - let config_tmpl = - fs::read_to_string(support::testdata_file("motd_pager_1s_debounce.toml.tmpl"))?; - let config_contents = config_tmpl.replace("TMP_MOTD_MSG_FILE", motd_file.to_str().unwrap()); - let config_file = tmp_dir.path().join("motd_pager.toml"); - { - let mut f = fs::File::create(&config_file)?; - f.write_all(config_contents.as_bytes())?; - } - - // spawn a daemon based on our custom config - let daemon_proc = support::daemon::Proc::new( - &config_file, - DaemonArgs { - extra_env: vec![(String::from("TERM"), String::from("xterm"))], - ..DaemonArgs::default() - }, - ) - .context("starting daemon proc")?; + // set up the config + let tmp_dir = tmpdir::Dir::new("/tmp/shpool-test")?; + eprintln!("building config in {:?}", tmp_dir.path()); + let motd_file = tmp_dir.path().join("motd.txt"); + { + let mut f = fs::File::create(&motd_file)?; + f.write_all("MOTD_MSG\n".as_bytes())?; + } + let config_tmpl = + fs::read_to_string(support::testdata_file("motd_pager_1s_debounce.toml.tmpl"))?; + let config_contents = config_tmpl.replace("TMP_MOTD_MSG_FILE", motd_file.to_str().unwrap()); + let config_file = tmp_dir.path().join("motd_pager.toml"); + { + let mut f = fs::File::create(&config_file)?; + f.write_all(config_contents.as_bytes())?; + } - let stdout_str = snapshot_attach_output( - &daemon_proc, - &config_file, - time::Duration::from_millis(500), - "sh1", - )?; - // scan for a fragment of less output - let stdout_file_re = Regex::new(".*\\(END\\).*")?; - assert!(stdout_file_re.is_match(&stdout_str)); - - // sleep for 1.1 seconds because the debounce duration is 1 second. - std::thread::sleep(time::Duration::from_millis(1100)); - - // We should see the message again when we try again after debounce. - let stdout_str = snapshot_attach_output( - &daemon_proc, - &config_file, - time::Duration::from_millis(500), - "sh2", - )?; - assert!(stdout_file_re.is_match(&stdout_str)); - - Ok(()) - }) + // spawn a daemon based on our custom config + let daemon_proc = support::daemon::Proc::new( + &config_file, + DaemonArgs { + extra_env: vec![(String::from("TERM"), String::from("xterm"))], + ..DaemonArgs::default() + }, + ) + .context("starting daemon proc")?; + + let stdout_str = snapshot_attach_output( + &daemon_proc, + &config_file, + time::Duration::from_millis(500), + "sh1", + )?; + // scan for a fragment of less output + let stdout_file_re = Regex::new(".*\\(END\\).*")?; + assert!(stdout_file_re.is_match(&stdout_str)); + + // sleep for 1.1 seconds because the debounce duration is 1 second. + std::thread::sleep(time::Duration::from_millis(1100)); + + // We should see the message again when we try again after debounce. + let stdout_str = snapshot_attach_output( + &daemon_proc, + &config_file, + time::Duration::from_millis(500), + "sh2", + )?; + assert!(stdout_file_re.is_match(&stdout_str)); + + Ok(()) } #[test] #[timeout(30000)] #[cfg_attr(target_os = "macos", ignore)] // pager pty output issue fn motd_env_test_pager_preserves_term_env_var() -> anyhow::Result<()> { - support::dump_err(|| { - // set up the config - let tmp_dir = tmpdir::Dir::new("/tmp/shpool-test")?; - eprintln!("building config in {:?}", tmp_dir.path()); - let config_tmpl = - fs::read_to_string(support::testdata_file("motd_pager_env_test.toml.tmpl"))?; - let config_contents = config_tmpl.replace( - "MOTD_ENV_TEST_SCRIPT", - support::testdata_file("motd_env_test_script.sh").to_str().unwrap(), - ); - let config_file = tmp_dir.path().join("motd_pager.toml"); - { - let mut f = fs::File::create(&config_file)?; - f.write_all(config_contents.as_bytes())?; - } - - // spawn a daemon based on our custom config - let daemon_proc = support::daemon::Proc::new(&config_file, DaemonArgs::default()) - .context("starting daemon proc")?; + // set up the config + let tmp_dir = tmpdir::Dir::new("/tmp/shpool-test")?; + eprintln!("building config in {:?}", tmp_dir.path()); + let config_tmpl = fs::read_to_string(support::testdata_file("motd_pager_env_test.toml.tmpl"))?; + let config_contents = config_tmpl.replace( + "MOTD_ENV_TEST_SCRIPT", + support::testdata_file("motd_env_test_script.sh").to_str().unwrap(), + ); + let config_file = tmp_dir.path().join("motd_pager.toml"); + { + let mut f = fs::File::create(&config_file)?; + f.write_all(config_contents.as_bytes())?; + } - let stdout_str = snapshot_attach_output( - &daemon_proc, - &config_file, - time::Duration::from_millis(500), - "sh1", - )?; - // Scan for a fragment of less output. - eprintln!("STDOUT: {stdout_str}"); - let stdout_file_re = Regex::new(".*TERM=testval.*")?; - assert!(stdout_file_re.is_match(&stdout_str)); - - Ok(()) - }) + // spawn a daemon based on our custom config + let daemon_proc = support::daemon::Proc::new(&config_file, DaemonArgs::default()) + .context("starting daemon proc")?; + + let stdout_str = snapshot_attach_output( + &daemon_proc, + &config_file, + time::Duration::from_millis(500), + "sh1", + )?; + // Scan for a fragment of less output. + eprintln!("STDOUT: {stdout_str}"); + let stdout_file_re = Regex::new(".*TERM=testval.*")?; + assert!(stdout_file_re.is_match(&stdout_str)); + + Ok(()) } #[test] #[timeout(30000)] fn dynamic_config_change() -> anyhow::Result<()> { - support::dump_err(|| { - let tmp_dir = tmpdir::Dir::new("/tmp/shpool-test")?; - eprintln!("building config in {:?}", tmp_dir.path()); - let config_tmpl = fs::read_to_string(support::testdata_file("dynamic_config.toml.tmpl"))?; - let config_file = tmp_dir.path().join("motd_pager.toml"); - fs::write(&config_file, &config_tmpl)?; - - let mut daemon_proc = - support::daemon::Proc::new(&config_file, DaemonArgs { ..DaemonArgs::default() }) - .context("starting daemon proc")?; + let tmp_dir = tmpdir::Dir::new("/tmp/shpool-test")?; + eprintln!("building config in {:?}", tmp_dir.path()); + let config_tmpl = fs::read_to_string(support::testdata_file("dynamic_config.toml.tmpl"))?; + let config_file = tmp_dir.path().join("motd_pager.toml"); + fs::write(&config_file, &config_tmpl)?; + + let mut daemon_proc = + support::daemon::Proc::new(&config_file, DaemonArgs { ..DaemonArgs::default() }) + .context("starting daemon proc")?; - let mut attach_proc = - daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; - let mut line_matcher = attach_proc.line_matcher()?; - attach_proc.run_cmd("echo $CHANGING_VAR")?; - line_matcher.scan_until_re("REPLACE_ME$")?; - - // Create waiter right before changing config file, since reload can also happen - // right after daemon startup. - let mut waiter = daemon_proc - .events - .take() - .unwrap() - .waiter(["daemon-config-watcher-file-change", "daemon-reload-config"]); - - // Change the config contents on the fly - let config_contents = config_tmpl.replace("REPLACE_ME", "NEW_VALUE"); - fs::write(&config_file, config_contents)?; - - // Wait for reload to happen since there is debounce time. - waiter.wait_event("daemon-config-watcher-file-change")?; - waiter.wait_event("daemon-reload-config")?; - - // When we spawn a new session, it should pick up the new value - let mut attach_proc = - daemon_proc.attach("sh2", Default::default()).context("starting attach proc")?; - let mut line_matcher = attach_proc.line_matcher()?; - attach_proc.run_cmd("echo $CHANGING_VAR")?; - line_matcher.scan_until_re("NEW_VALUE$")?; + let mut attach_proc = + daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; + let mut line_matcher = attach_proc.line_matcher()?; + attach_proc.run_cmd("echo $CHANGING_VAR")?; + line_matcher.scan_until_re("REPLACE_ME$")?; + + // Create waiter right before changing config file, since reload can also happen + // right after daemon startup. + let mut waiter = daemon_proc + .events + .take() + .unwrap() + .waiter(["daemon-config-watcher-file-change", "daemon-reload-config"]); + + // Change the config contents on the fly + let config_contents = config_tmpl.replace("REPLACE_ME", "NEW_VALUE"); + fs::write(&config_file, config_contents)?; + + // Wait for reload to happen since there is debounce time. + waiter.wait_event("daemon-config-watcher-file-change")?; + waiter.wait_event("daemon-reload-config")?; + + // When we spawn a new session, it should pick up the new value + let mut attach_proc = + daemon_proc.attach("sh2", Default::default()).context("starting attach proc")?; + let mut line_matcher = attach_proc.line_matcher()?; + attach_proc.run_cmd("echo $CHANGING_VAR")?; + line_matcher.scan_until_re("NEW_VALUE$")?; - Ok(()) - }) + Ok(()) } #[test] #[timeout(30000)] fn fresh_shell_does_not_have_prompt_setup_code() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) - .context("starting daemon proc")?; + let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) + .context("starting daemon proc")?; - let mut attach_proc = - daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; - let mut reader = std::io::BufReader::new( - attach_proc.proc.stdout.take().ok_or(anyhow!("missing stdout"))?, - ); + let mut attach_proc = + daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; + let mut reader = + std::io::BufReader::new(attach_proc.proc.stdout.take().ok_or(anyhow!("missing stdout"))?); - let mut output = vec![]; - reader.read_until(b'>', &mut output)?; - let chunk = String::from_utf8_lossy(&output[..]); - assert!(!chunk.contains("SHPOOL__OLD_PROMPT_COMMAND")); + let mut output = vec![]; + reader.read_until(b'>', &mut output)?; + let chunk = String::from_utf8_lossy(&output[..]); + assert!(!chunk.contains("SHPOOL__OLD_PROMPT_COMMAND")); - Ok(()) - }) + Ok(()) } #[test] #[timeout(30000)] fn autodaemonize() -> anyhow::Result<()> { - support::dump_err(|| { - let tmp_dir = tmpdir::Dir::new("/tmp/shpool-test")?; - eprintln!("testing autodaemonization in {:?}", tmp_dir.path()); - - let mut socket_path = PathBuf::from(tmp_dir.path()); - socket_path.push("control.sock"); - - let mut log_file = PathBuf::from(tmp_dir.path()); - log_file.push("attach.log"); - - // we have to manually spawn the child because the whole point is that there - // isn't a daemon yet so we can't use the attach method. - let mut child = Command::new(support::shpool_bin()?) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .arg("--daemonize") - .arg("--socket") - .arg(socket_path) - .arg("--log-file") - .arg(log_file) - .arg("--config-file") - .arg(support::testdata_file("norc.toml")) - .arg("attach") - .arg("sh1") - .spawn() - .context("spawning attach process")?; - - // After half a second, the daemon should have spanwed - std::thread::sleep(time::Duration::from_millis(500)); - child.kill().context("killing child")?; - - let mut stdout = child.stdout.take().context("missing stdout")?; - let mut stdout_str = String::from(""); - stdout.read_to_string(&mut stdout_str).context("slurping stdout")?; - let stdout_re = Regex::new(".*prompt>.*")?; - assert!(stdout_re.is_match(&stdout_str)); - - // best effort attempt to clean up after ourselves - Command::new("pkill") - .arg("-f") - .arg("shpool-test-autodaemonize") - .output() - .context("running cleanup process")?; - - Ok(()) - }) + let tmp_dir = tmpdir::Dir::new("/tmp/shpool-test")?; + eprintln!("testing autodaemonization in {:?}", tmp_dir.path()); + + let mut socket_path = PathBuf::from(tmp_dir.path()); + socket_path.push("control.sock"); + + let mut log_file = PathBuf::from(tmp_dir.path()); + log_file.push("attach.log"); + + // we have to manually spawn the child because the whole point is that there + // isn't a daemon yet so we can't use the attach method. + let mut child = Command::new(support::shpool_bin()?) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .arg("--daemonize") + .arg("--socket") + .arg(socket_path) + .arg("--log-file") + .arg(log_file) + .arg("--config-file") + .arg(support::testdata_file("norc.toml")) + .arg("attach") + .arg("sh1") + .spawn() + .context("spawning attach process")?; + + // After half a second, the daemon should have spanwed + std::thread::sleep(time::Duration::from_millis(500)); + child.kill().context("killing child")?; + + let mut stdout = child.stdout.take().context("missing stdout")?; + let mut stdout_str = String::from(""); + stdout.read_to_string(&mut stdout_str).context("slurping stdout")?; + let stdout_re = Regex::new(".*prompt>.*")?; + assert!(stdout_re.is_match(&stdout_str)); + + // best effort attempt to clean up after ourselves + Command::new("pkill") + .arg("-f") + .arg("shpool-test-autodaemonize") + .output() + .context("running cleanup process")?; + + Ok(()) } #[test] #[timeout(30000)] fn config_tmp_default_dir() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = - support::daemon::Proc::new("tmp_default_dir.toml", DaemonArgs::default()) - .context("starting daemon proc")?; - let mut attach_proc = daemon_proc - .attach( - "sh1", - AttachArgs { - config: Some(String::from("tmp_default_dir.toml")), - ..Default::default() - }, - ) - .context("starting attach proc")?; + let mut daemon_proc = support::daemon::Proc::new("tmp_default_dir.toml", DaemonArgs::default()) + .context("starting daemon proc")?; + let mut attach_proc = daemon_proc + .attach( + "sh1", + AttachArgs { config: Some(String::from("tmp_default_dir.toml")), ..Default::default() }, + ) + .context("starting attach proc")?; - let mut line_matcher = attach_proc.line_matcher()?; + let mut line_matcher = attach_proc.line_matcher()?; - attach_proc.run_cmd("pwd")?; - line_matcher.scan_until_re("tmp$")?; + attach_proc.run_cmd("pwd")?; + line_matcher.scan_until_re("tmp$")?; - Ok(()) - }) + Ok(()) } #[test] #[timeout(30000)] fn cli_tmp_dir() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) - .context("starting daemon proc")?; - let mut attach_proc = daemon_proc - .attach("sh1", AttachArgs { dir: Some(String::from("/tmp")), ..Default::default() }) - .context("starting attach proc")?; + let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) + .context("starting daemon proc")?; + let mut attach_proc = daemon_proc + .attach("sh1", AttachArgs { dir: Some(String::from("/tmp")), ..Default::default() }) + .context("starting attach proc")?; - let mut line_matcher = attach_proc.line_matcher()?; + let mut line_matcher = attach_proc.line_matcher()?; - attach_proc.run_cmd("pwd")?; - line_matcher.scan_until_re("tmp$")?; + attach_proc.run_cmd("pwd")?; + line_matcher.scan_until_re("tmp$")?; - Ok(()) - }) + Ok(()) } #[test] #[timeout(30000)] fn version_mismatch_client_newer() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new( - "norc.toml", - DaemonArgs { - extra_env: vec![( - String::from("SHPOOL_TEST__OVERRIDE_VERSION"), - String::from("0.0.0"), - )], - ..DaemonArgs::default() - }, - ) - .context("starting daemon proc")?; - let mut attach_proc = - daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; - let mut line_matcher = attach_proc.line_matcher()?; - let mut stderr_line_matcher = attach_proc.stderr_line_matcher()?; + let mut daemon_proc = support::daemon::Proc::new( + "norc.toml", + DaemonArgs { + extra_env: vec![(String::from("SHPOOL_TEST__OVERRIDE_VERSION"), String::from("0.0.0"))], + ..DaemonArgs::default() + }, + ) + .context("starting daemon proc")?; + let mut attach_proc = + daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; + let mut line_matcher = attach_proc.line_matcher()?; + let mut stderr_line_matcher = attach_proc.stderr_line_matcher()?; - // we should see a warning prompting us - stderr_line_matcher.scan_until_re("is newer.*try restarting your daemon$")?; - stderr_line_matcher.scan_until_re("hit enter to continue.*$")?; - attach_proc.run_cmd("")?; // continue through it + // we should see a warning prompting us + stderr_line_matcher.scan_until_re("is newer.*try restarting your daemon$")?; + stderr_line_matcher.scan_until_re("hit enter to continue.*$")?; + attach_proc.run_cmd("")?; // continue through it - // not really needed, just here to test the events system - attach_proc.run_cmd("echo hi")?; - line_matcher.scan_until_re("hi$")?; + // not really needed, just here to test the events system + attach_proc.run_cmd("echo hi")?; + line_matcher.scan_until_re("hi$")?; - Ok(()) - }) + Ok(()) } #[ignore] // TODO: re-enable, this test if flaky diff --git a/shpool/tests/daemon.rs b/shpool/tests/daemon.rs index 64243a54..0957ba48 100644 --- a/shpool/tests/daemon.rs +++ b/shpool/tests/daemon.rs @@ -25,301 +25,277 @@ use crate::support::{ #[test] #[timeout(30000)] fn start() -> anyhow::Result<()> { - support::dump_err(|| { - let tmp_dir = tmpdir::Dir::new("/tmp/shpool-test")?; - - let mut child = Command::new(support::shpool_bin()?) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .arg("--socket") - .arg(tmp_dir.path().join("shpool.socket")) - .arg("daemon") - .spawn() - .context("spawning daemon process")?; - - // The server should start up and run without incident for - // half a second. - std::thread::sleep(time::Duration::from_millis(500)); - - child.kill().context("killing child")?; - - let mut stdout = child.stdout.take().context("missing stdout")?; - let mut stdout_str = String::from(""); - stdout.read_to_string(&mut stdout_str).context("slurping stdout")?; - - if !stdout_str.is_empty() { - println!("{stdout_str}"); - return Err(anyhow!("unexpected stdout output")); - } - - let mut stderr = child.stderr.take().context("missing stderr")?; - let mut stderr_str = String::from(""); - stderr.read_to_string(&mut stderr_str).context("slurping stderr")?; - assert!(stderr_str.contains("STARTING DAEMON")); - - Ok(()) - }) + let tmp_dir = tmpdir::Dir::new("/tmp/shpool-test")?; + + let mut child = Command::new(support::shpool_bin()?) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .arg("--socket") + .arg(tmp_dir.path().join("shpool.socket")) + .arg("daemon") + .spawn() + .context("spawning daemon process")?; + + // The server should start up and run without incident for + // half a second. + std::thread::sleep(time::Duration::from_millis(500)); + + child.kill().context("killing child")?; + + let mut stdout = child.stdout.take().context("missing stdout")?; + let mut stdout_str = String::from(""); + stdout.read_to_string(&mut stdout_str).context("slurping stdout")?; + + if !stdout_str.is_empty() { + println!("{stdout_str}"); + return Err(anyhow!("unexpected stdout output")); + } + + let mut stderr = child.stderr.take().context("missing stderr")?; + let mut stderr_str = String::from(""); + stderr.read_to_string(&mut stderr_str).context("slurping stderr")?; + assert!(stderr_str.contains("STARTING DAEMON")); + + Ok(()) } #[test] #[timeout(30000)] #[cfg_attr(target_os = "macos", ignore)] // systemd activation is a linux only feature fn systemd_activation() -> anyhow::Result<()> { - support::dump_err(|| { - let tmp_dir = tmpdir::Dir::new("/tmp/shpool-test")?; - let sock_path = tmp_dir.path().join("shpool.socket"); - let activation_sock = UnixListener::bind(&sock_path)?; - - let (parent_stderr, child_stderr) = - nix::unistd::pipe().context("creating pipe to collect stderr")?; - let child_stderr_pipe = Stdio::from(child_stderr); - let mut cmd = Command::new(support::shpool_bin()?); - cmd.stdout(Stdio::piped()) - .stderr(child_stderr_pipe) - .env("LISTEN_FDS", "1") - .env("LISTEN_FDNAMES", sock_path) - .arg("daemon"); - - let mut pid_buf = String::with_capacity(128); - - // We use fork both so we can correctly set LISTEN_PID and so - // that the daemon will inherit the socket fd the way that we - // want. - // - // We have to manually fork rather than using pre_exec because - // there does not appear to be a way to set an environment - // variable the child will inherit in the pre_exec callback. - // - // Safety: it's a test, get off my back. I try to avoid allocating. - let child_pid = match unsafe { nix::unistd::fork() } { - Ok(ForkResult::Parent { child, .. }) => child, - Ok(ForkResult::Child) => { - // place the unix socket file descriptor in the right place - // Safety: We are sure that FD 3 is not open, and the returned OwnedFd will be - // its only owner. - let fdarg = match unsafe { nix::unistd::dup2_raw(activation_sock, 3) } { - Ok(newfd) => newfd, - Err(e) => { - eprintln!("dup err: {e}"); - std::process::exit(1) - } - }; - - // unset the fd_cloexec flag on the file descriptor so - // we can actuall pass it down to the child - let fdflags = nix::fcntl::fcntl(&fdarg, nix::fcntl::FcntlArg::F_GETFD) - .expect("getfd flags to work"); - let mut newflags = nix::fcntl::FdFlag::from_bits(fdflags).unwrap(); - newflags.remove(nix::fcntl::FdFlag::FD_CLOEXEC); - nix::fcntl::fcntl(&fdarg, nix::fcntl::FcntlArg::F_SETFD(newflags)) - .expect("FD_CLOEXEC to be unset"); - - // set the LISTEN_PID environment variable without - // allocating - write!(&mut pid_buf, "{}", std::process::id()) - .expect("to be able to format the pid"); - cmd.env("LISTEN_PID", pid_buf); - - let err = cmd.exec(); - eprintln!("exec err: {err:?}"); - std::process::exit(1); - } - Err(e) => { - return Err(e).context("forking daemon proc"); - } - }; - - // The server should start up and run without incident for - // half a second. - std::thread::sleep(time::Duration::from_millis(500)); - - // kill the daemon proc and reap the return code - nix::sys::signal::kill(child_pid, Some(nix::sys::signal::Signal::SIGKILL)) - .context("killing daemon")?; - nix::sys::wait::waitpid(child_pid, None).context("reaping daemon")?; - - let mut stderr_buf: Vec = vec![0; 1024 * 8]; - let len = - nix::unistd::read(&parent_stderr, &mut stderr_buf[..]).context("reading stderr")?; - let stderr = String::from_utf8_lossy(&stderr_buf[..len]); - assert!(stderr.contains("using systemd activation socket")); - - Ok(()) - }) + let tmp_dir = tmpdir::Dir::new("/tmp/shpool-test")?; + let sock_path = tmp_dir.path().join("shpool.socket"); + let activation_sock = UnixListener::bind(&sock_path)?; + + let (parent_stderr, child_stderr) = + nix::unistd::pipe().context("creating pipe to collect stderr")?; + let child_stderr_pipe = Stdio::from(child_stderr); + let mut cmd = Command::new(support::shpool_bin()?); + cmd.stdout(Stdio::piped()) + .stderr(child_stderr_pipe) + .env("LISTEN_FDS", "1") + .env("LISTEN_FDNAMES", sock_path) + .arg("daemon"); + + let mut pid_buf = String::with_capacity(128); + + // We use fork both so we can correctly set LISTEN_PID and so + // that the daemon will inherit the socket fd the way that we + // want. + // + // We have to manually fork rather than using pre_exec because + // there does not appear to be a way to set an environment + // variable the child will inherit in the pre_exec callback. + // + // Safety: it's a test, get off my back. I try to avoid allocating. + let child_pid = match unsafe { nix::unistd::fork() } { + Ok(ForkResult::Parent { child, .. }) => child, + Ok(ForkResult::Child) => { + // place the unix socket file descriptor in the right place + // Safety: We are sure that FD 3 is not open, and the returned OwnedFd will be + // its only owner. + let fdarg = match unsafe { nix::unistd::dup2_raw(activation_sock, 3) } { + Ok(newfd) => newfd, + Err(e) => { + eprintln!("dup err: {e}"); + std::process::exit(1) + } + }; + + // unset the fd_cloexec flag on the file descriptor so + // we can actuall pass it down to the child + let fdflags = nix::fcntl::fcntl(&fdarg, nix::fcntl::FcntlArg::F_GETFD) + .expect("getfd flags to work"); + let mut newflags = nix::fcntl::FdFlag::from_bits(fdflags).unwrap(); + newflags.remove(nix::fcntl::FdFlag::FD_CLOEXEC); + nix::fcntl::fcntl(&fdarg, nix::fcntl::FcntlArg::F_SETFD(newflags)) + .expect("FD_CLOEXEC to be unset"); + + // set the LISTEN_PID environment variable without + // allocating + write!(&mut pid_buf, "{}", std::process::id()).expect("to be able to format the pid"); + cmd.env("LISTEN_PID", pid_buf); + + let err = cmd.exec(); + eprintln!("exec err: {err:?}"); + std::process::exit(1); + } + Err(e) => { + return Err(e).context("forking daemon proc"); + } + }; + + // The server should start up and run without incident for + // half a second. + std::thread::sleep(time::Duration::from_millis(500)); + + // kill the daemon proc and reap the return code + nix::sys::signal::kill(child_pid, Some(nix::sys::signal::Signal::SIGKILL)) + .context("killing daemon")?; + nix::sys::wait::waitpid(child_pid, None).context("reaping daemon")?; + + let mut stderr_buf: Vec = vec![0; 1024 * 8]; + let len = nix::unistd::read(&parent_stderr, &mut stderr_buf[..]).context("reading stderr")?; + let stderr = String::from_utf8_lossy(&stderr_buf[..len]); + assert!(stderr.contains("using systemd activation socket")); + + Ok(()) } #[test] #[timeout(30000)] fn config() -> anyhow::Result<()> { - support::dump_err(|| { - let tmp_dir = tmpdir::Dir::new("/tmp/shpool-test")?; - - let mut child = Command::new(support::shpool_bin()?) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .arg("--socket") - .arg(tmp_dir.path().join("shpool.socket")) - .arg("--config-file") - .arg(support::testdata_file("empty.toml")) - .arg("daemon") - .spawn() - .context("spawning daemon process")?; - - // The server should start up and run without incident for - // half a second. - std::thread::sleep(time::Duration::from_millis(500)); - - child.kill().context("killing child")?; - - let mut stdout = child.stdout.take().context("missing stdout")?; - let mut stdout_str = String::from(""); - stdout.read_to_string(&mut stdout_str).context("slurping stdout")?; - - if !stdout_str.is_empty() { - println!("{stdout_str}"); - return Err(anyhow!("unexpected stdout output")); - } - - let mut stderr = child.stderr.take().context("missing stderr")?; - let mut stderr_str = String::from(""); - stderr.read_to_string(&mut stderr_str).context("slurping stderr")?; - assert!(stderr_str.contains("STARTING DAEMON")); - - Ok(()) - }) + let tmp_dir = tmpdir::Dir::new("/tmp/shpool-test")?; + + let mut child = Command::new(support::shpool_bin()?) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .arg("--socket") + .arg(tmp_dir.path().join("shpool.socket")) + .arg("--config-file") + .arg(support::testdata_file("empty.toml")) + .arg("daemon") + .spawn() + .context("spawning daemon process")?; + + // The server should start up and run without incident for + // half a second. + std::thread::sleep(time::Duration::from_millis(500)); + + child.kill().context("killing child")?; + + let mut stdout = child.stdout.take().context("missing stdout")?; + let mut stdout_str = String::from(""); + stdout.read_to_string(&mut stdout_str).context("slurping stdout")?; + + if !stdout_str.is_empty() { + println!("{stdout_str}"); + return Err(anyhow!("unexpected stdout output")); + } + + let mut stderr = child.stderr.take().context("missing stderr")?; + let mut stderr_str = String::from(""); + stderr.read_to_string(&mut stderr_str).context("slurping stderr")?; + assert!(stderr_str.contains("STARTING DAEMON")); + + Ok(()) } #[test] #[timeout(30000)] fn hooks() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = - support::daemon::Proc::new_instrumented("norc.toml").context("starting daemon proc")?; - let sh1_detached_re = Regex::new("sh1.*disconnected")?; - - { - // 1 new session - let mut sh1_proc = daemon_proc - .attach( - "sh1", - AttachArgs { cmd: Some(String::from("/bin/bash")), ..Default::default() }, - ) - .context("starting attach proc")?; - - // sequencing - let mut sh1_matcher = sh1_proc.line_matcher()?; - sh1_proc.run_cmd("echo hi")?; - sh1_matcher.scan_until_re("hi$")?; - - // 1 busy - let mut busy_proc = daemon_proc - .attach( - "sh1", - AttachArgs { cmd: Some(String::from("/bin/bash")), ..Default::default() }, - ) - .context("starting attach proc")?; - busy_proc.proc.wait()?; - } // 1 client disconnect - - // spin until sh1 disconnects - daemon_proc.wait_until_list_matches(|listout| sh1_detached_re.is_match(listout))?; - - // 1 reattach + let mut daemon_proc = + support::daemon::Proc::new_instrumented("norc.toml").context("starting daemon proc")?; + let sh1_detached_re = Regex::new("sh1.*disconnected")?; + + { + // 1 new session let mut sh1_proc = daemon_proc .attach( "sh1", AttachArgs { cmd: Some(String::from("/bin/bash")), ..Default::default() }, ) .context("starting attach proc")?; - sh1_proc.run_cmd("exit")?; // 1 shell disconnect - support::wait_until(|| { - let hook_records = daemon_proc.hook_records.as_ref().unwrap().lock().unwrap(); - Ok(!hook_records.shell_disconnects.is_empty()) - })?; + // sequencing + let mut sh1_matcher = sh1_proc.line_matcher()?; + sh1_proc.run_cmd("echo hi")?; + sh1_matcher.scan_until_re("hi$")?; + // 1 busy + let mut busy_proc = daemon_proc + .attach( + "sh1", + AttachArgs { cmd: Some(String::from("/bin/bash")), ..Default::default() }, + ) + .context("starting attach proc")?; + busy_proc.proc.wait()?; + } // 1 client disconnect + + // spin until sh1 disconnects + daemon_proc.wait_until_list_matches(|listout| sh1_detached_re.is_match(listout))?; + + // 1 reattach + let mut sh1_proc = daemon_proc + .attach("sh1", AttachArgs { cmd: Some(String::from("/bin/bash")), ..Default::default() }) + .context("starting attach proc")?; + sh1_proc.run_cmd("exit")?; // 1 shell disconnect + + support::wait_until(|| { let hook_records = daemon_proc.hook_records.as_ref().unwrap().lock().unwrap(); - eprintln!("hook_records: {hook_records:?}"); - assert_eq!(hook_records.new_sessions[0], "sh1"); - assert_eq!(hook_records.reattaches[0], "sh1"); - assert_eq!(hook_records.busys[0], "sh1"); - assert_eq!(hook_records.client_disconnects[0], "sh1"); - assert_eq!(hook_records.shell_disconnects[0], "sh1"); - - Ok(()) - }) + Ok(!hook_records.shell_disconnects.is_empty()) + })?; + + let hook_records = daemon_proc.hook_records.as_ref().unwrap().lock().unwrap(); + eprintln!("hook_records: {hook_records:?}"); + assert_eq!(hook_records.new_sessions[0], "sh1"); + assert_eq!(hook_records.reattaches[0], "sh1"); + assert_eq!(hook_records.busys[0], "sh1"); + assert_eq!(hook_records.client_disconnects[0], "sh1"); + assert_eq!(hook_records.shell_disconnects[0], "sh1"); + + Ok(()) } #[test] #[timeout(30000)] fn cleanup_socket() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new( - "norc.toml", - DaemonArgs { listen_events: false, ..DaemonArgs::default() }, - ) - .context("starting daemon proc")?; - - signal::kill( - Pid::from_raw(daemon_proc.proc.as_ref().unwrap().id() as i32), - Signal::SIGINT, - )?; - - daemon_proc.proc_wait()?; - - assert!(!path::Path::new(&daemon_proc.socket_path).exists()); - Ok(()) - }) + let mut daemon_proc = support::daemon::Proc::new( + "norc.toml", + DaemonArgs { listen_events: false, ..DaemonArgs::default() }, + ) + .context("starting daemon proc")?; + + signal::kill(Pid::from_raw(daemon_proc.proc.as_ref().unwrap().id() as i32), Signal::SIGINT)?; + + daemon_proc.proc_wait()?; + + assert!(!path::Path::new(&daemon_proc.socket_path).exists()); + Ok(()) } #[test] #[timeout(30000)] fn echo_sentinel() -> anyhow::Result<()> { - support::dump_err(|| { - let output = Command::new(support::shpool_bin()?) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .env("SHPOOL__INTERNAL__PRINT_SENTINEL", "prompt") - .arg("daemon") - .output()?; - - assert!(output.status.success()); - let stdout = String::from_utf8_lossy(&output.stdout); - assert!(stdout.contains("SHPOOL_PROMPT_SETUP_SENTINEL")); - - Ok(()) - }) + let output = Command::new(support::shpool_bin()?) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .env("SHPOOL__INTERNAL__PRINT_SENTINEL", "prompt") + .arg("daemon") + .output()?; + + assert!(output.status.success()); + let stdout = String::from_utf8_lossy(&output.stdout); + assert!(stdout.contains("SHPOOL_PROMPT_SETUP_SENTINEL")); + + Ok(()) } #[test] #[timeout(30000)] fn allows_dynamic_log_adjustments() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new( - "norc.toml", - DaemonArgs { verbosity: 0, ..Default::default() }, - ) - .context("starting daemon proc")?; - - daemon_proc.set_log_level("trace")?; - - // Loop because the data might not get flushed the first time through. - loop { - let mut sh1 = daemon_proc.attach("sh1", AttachArgs::default())?; - // let mut line_matcher1 = sh1.line_matcher()?; - sh1.run_cmd("echo hi")?; - // line_matcher1.scan_until_re("hi$")?; - - // Make sure trace level data landed in the log despite the fact - // that we started the daemon with a verbosity level of 0. - let log_data = std::fs::read_to_string(&daemon_proc.log_file)?; - if log_data.contains("echo hi") { - break; - } - - std::thread::sleep(time::Duration::from_millis(300)); + let mut daemon_proc = + support::daemon::Proc::new("norc.toml", DaemonArgs { verbosity: 0, ..Default::default() }) + .context("starting daemon proc")?; + + daemon_proc.set_log_level("trace")?; + + // Loop because the data might not get flushed the first time through. + loop { + let mut sh1 = daemon_proc.attach("sh1", AttachArgs::default())?; + // let mut line_matcher1 = sh1.line_matcher()?; + sh1.run_cmd("echo hi")?; + // line_matcher1.scan_until_re("hi$")?; + + // Make sure trace level data landed in the log despite the fact + // that we started the daemon with a verbosity level of 0. + let log_data = std::fs::read_to_string(&daemon_proc.log_file)?; + if log_data.contains("echo hi") { + break; } - Ok(()) - }) + std::thread::sleep(time::Duration::from_millis(300)); + } + + Ok(()) } diff --git a/shpool/tests/detach.rs b/shpool/tests/detach.rs index 271d313a..ed208e80 100644 --- a/shpool/tests/detach.rs +++ b/shpool/tests/detach.rs @@ -12,292 +12,269 @@ use crate::support::daemon::DaemonArgs; #[test] #[timeout(30000)] fn single_running() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) - .context("starting daemon proc")?; + let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) + .context("starting daemon proc")?; - let mut waiter = daemon_proc - .events - .take() - .unwrap() - .waiter(["daemon-bidi-stream-enter", "daemon-bidi-stream-done"]); - let mut attach_proc = - daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; - waiter.wait_event("daemon-bidi-stream-enter")?; + let mut waiter = daemon_proc + .events + .take() + .unwrap() + .waiter(["daemon-bidi-stream-enter", "daemon-bidi-stream-done"]); + let mut attach_proc = + daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; + waiter.wait_event("daemon-bidi-stream-enter")?; - let out = daemon_proc.detach(vec![String::from("sh1")])?; - assert!(out.status.success(), "not successful"); + let out = daemon_proc.detach(vec![String::from("sh1")])?; + assert!(out.status.success(), "not successful"); - let stderr = String::from_utf8_lossy(&out.stderr[..]); - assert_eq!(stderr.len(), 0, "expected no stderr"); + let stderr = String::from_utf8_lossy(&out.stderr[..]); + assert_eq!(stderr.len(), 0, "expected no stderr"); - let stdout = String::from_utf8_lossy(&out.stdout[..]); - assert_eq!(stdout.len(), 0, "expected no stdout"); + let stdout = String::from_utf8_lossy(&out.stdout[..]); + assert_eq!(stdout.len(), 0, "expected no stdout"); - daemon_proc.events = Some(waiter.wait_final_event("daemon-bidi-stream-done")?); + daemon_proc.events = Some(waiter.wait_final_event("daemon-bidi-stream-done")?); - let attach_exit_status = attach_proc.proc.wait()?; - assert!(attach_exit_status.success()); + let attach_exit_status = attach_proc.proc.wait()?; + assert!(attach_exit_status.success()); - Ok(()) - }) + Ok(()) } #[test] #[timeout(30000)] fn version_mismatch_client_newer() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new( - "norc.toml", - DaemonArgs { - extra_env: vec![( - String::from("SHPOOL_TEST__OVERRIDE_VERSION"), - String::from("0.0.0"), - )], - ..DaemonArgs::default() - }, - ) - .context("starting daemon proc")?; + let mut daemon_proc = support::daemon::Proc::new( + "norc.toml", + DaemonArgs { + extra_env: vec![(String::from("SHPOOL_TEST__OVERRIDE_VERSION"), String::from("0.0.0"))], + ..DaemonArgs::default() + }, + ) + .context("starting daemon proc")?; - let waiter = daemon_proc.events.take().unwrap().waiter(["daemon-bidi-stream-enter"]); - let mut attach_proc = - daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; + let waiter = daemon_proc.events.take().unwrap().waiter(["daemon-bidi-stream-enter"]); + let mut attach_proc = + daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; - // get past the version mismatch prompt - attach_proc.run_cmd("")?; + // get past the version mismatch prompt + attach_proc.run_cmd("")?; - daemon_proc.events = Some(waiter.wait_final_event("daemon-bidi-stream-enter")?); + daemon_proc.events = Some(waiter.wait_final_event("daemon-bidi-stream-enter")?); - let out = daemon_proc.detach(vec![String::from("sh1")])?; - assert!(out.status.success()); + let out = daemon_proc.detach(vec![String::from("sh1")])?; + assert!(out.status.success()); - let stderr = String::from_utf8_lossy(&out.stderr[..]); - assert!(stderr.contains("is newer")); - assert!(stderr.contains("try restarting")); + let stderr = String::from_utf8_lossy(&out.stderr[..]); + assert!(stderr.contains("is newer")); + assert!(stderr.contains("try restarting")); - Ok(()) - }) + Ok(()) } #[test] #[timeout(30000)] fn single_not_running() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new( - "norc.toml", - DaemonArgs { listen_events: false, ..DaemonArgs::default() }, - ) - .context("starting daemon proc")?; + let mut daemon_proc = support::daemon::Proc::new( + "norc.toml", + DaemonArgs { listen_events: false, ..DaemonArgs::default() }, + ) + .context("starting daemon proc")?; - let out = daemon_proc.detach(vec![String::from("sh1")])?; - assert!(!out.status.success(), "successful"); + let out = daemon_proc.detach(vec![String::from("sh1")])?; + assert!(!out.status.success(), "successful"); - let stderr = String::from_utf8_lossy(&out.stderr[..]); - assert!(stderr.contains("not found: sh1")); + let stderr = String::from_utf8_lossy(&out.stderr[..]); + assert!(stderr.contains("not found: sh1")); - let stdout = String::from_utf8_lossy(&out.stdout[..]); - assert_eq!(stdout.len(), 0, "expected no stderr"); + let stdout = String::from_utf8_lossy(&out.stdout[..]); + assert_eq!(stdout.len(), 0, "expected no stderr"); - Ok(()) - }) + Ok(()) } #[test] #[timeout(30000)] fn no_daemon() -> anyhow::Result<()> { - support::dump_err(|| { - let out = Command::new(support::shpool_bin()?) - .arg("--socket") - .arg("/fake/does/not/exist/shpool.socket") - .arg("--no-daemonize") - .arg("detach") - .output() - .context("spawning detach proc")?; - - assert!(!out.status.success(), "detach proc exited successfully"); - - let stderr = String::from_utf8_lossy(&out.stderr[..]); - assert!(stderr.contains("could not connect to daemon")); - - Ok(()) - }) + let out = Command::new(support::shpool_bin()?) + .arg("--socket") + .arg("/fake/does/not/exist/shpool.socket") + .arg("--no-daemonize") + .arg("detach") + .output() + .context("spawning detach proc")?; + + assert!(!out.status.success(), "detach proc exited successfully"); + + let stderr = String::from_utf8_lossy(&out.stderr[..]); + assert!(stderr.contains("could not connect to daemon")); + + Ok(()) } #[test] #[timeout(30000)] fn running_env_var() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) - .context("starting daemon proc")?; - - let mut waiter = daemon_proc - .events - .take() - .unwrap() - .waiter(["daemon-bidi-stream-enter", "daemon-bidi-stream-done"]); - let _attach_proc = - daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; - waiter.wait_event("daemon-bidi-stream-enter")?; - - let out = Command::new(support::shpool_bin()?) - .arg("--socket") - .arg(&daemon_proc.socket_path) - .arg("detach") - .env("SHPOOL_SESSION_NAME", "sh1") - .output() - .context("spawning detach cmd")?; - assert!(out.status.success(), "not successful"); - - let stderr = String::from_utf8_lossy(&out.stderr[..]); - assert_eq!(stderr.len(), 0, "expected no stderr"); - - let stdout = String::from_utf8_lossy(&out.stdout[..]); - assert_eq!(stdout.len(), 0, "expected no stdout"); - - daemon_proc.events = Some(waiter.wait_final_event("daemon-bidi-stream-done")?); - - Ok(()) - }) + let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) + .context("starting daemon proc")?; + + let mut waiter = daemon_proc + .events + .take() + .unwrap() + .waiter(["daemon-bidi-stream-enter", "daemon-bidi-stream-done"]); + let _attach_proc = + daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; + waiter.wait_event("daemon-bidi-stream-enter")?; + + let out = Command::new(support::shpool_bin()?) + .arg("--socket") + .arg(&daemon_proc.socket_path) + .arg("detach") + .env("SHPOOL_SESSION_NAME", "sh1") + .output() + .context("spawning detach cmd")?; + assert!(out.status.success(), "not successful"); + + let stderr = String::from_utf8_lossy(&out.stderr[..]); + assert_eq!(stderr.len(), 0, "expected no stderr"); + + let stdout = String::from_utf8_lossy(&out.stdout[..]); + assert_eq!(stdout.len(), 0, "expected no stdout"); + + daemon_proc.events = Some(waiter.wait_final_event("daemon-bidi-stream-done")?); + + Ok(()) } #[test] #[timeout(30000)] fn reattach() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) - .context("starting daemon proc")?; + let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) + .context("starting daemon proc")?; - let bidi_done_w = daemon_proc.events.take().unwrap().waiter(["daemon-bidi-stream-done"]); - let mut sess1 = - daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; + let bidi_done_w = daemon_proc.events.take().unwrap().waiter(["daemon-bidi-stream-done"]); + let mut sess1 = + daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; - let mut lm1 = sess1.line_matcher()?; - sess1.run_cmd("export MYVAR=first ; echo hi")?; - lm1.scan_until_re("hi$")?; + let mut lm1 = sess1.line_matcher()?; + sess1.run_cmd("export MYVAR=first ; echo hi")?; + lm1.scan_until_re("hi$")?; - let out = daemon_proc.detach(vec![String::from("sh1")])?; - assert!(out.status.success(), "not successful"); + let out = daemon_proc.detach(vec![String::from("sh1")])?; + assert!(out.status.success(), "not successful"); - let stderr = String::from_utf8_lossy(&out.stderr[..]); - assert_eq!(stderr.len(), 0, "expected no stderr"); + let stderr = String::from_utf8_lossy(&out.stderr[..]); + assert_eq!(stderr.len(), 0, "expected no stderr"); - let stdout = String::from_utf8_lossy(&out.stdout[..]); - assert_eq!(stdout.len(), 0, "expected no stdout"); + let stdout = String::from_utf8_lossy(&out.stdout[..]); + assert_eq!(stdout.len(), 0, "expected no stdout"); - daemon_proc.events = Some(bidi_done_w.wait_final_event("daemon-bidi-stream-done")?); + daemon_proc.events = Some(bidi_done_w.wait_final_event("daemon-bidi-stream-done")?); - let mut sess2 = - daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; - let mut lm2 = sess2.line_matcher()?; - sess2.run_cmd("echo ${MYVAR:-second}")?; - lm2.match_re("first$")?; + let mut sess2 = + daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; + let mut lm2 = sess2.line_matcher()?; + sess2.run_cmd("echo ${MYVAR:-second}")?; + lm2.match_re("first$")?; - Ok(()) - }) + Ok(()) } #[test] #[timeout(30000)] fn multiple_running() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) - .context("starting daemon proc")?; - - let mut waiter = daemon_proc.events.take().unwrap().waiter([ - "daemon-bidi-stream-enter", - "daemon-bidi-stream-enter", - "daemon-bidi-stream-done", - "daemon-bidi-stream-done", - ]); - let _sess1 = - daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; - waiter.wait_event("daemon-bidi-stream-enter")?; - - let _sess2 = - daemon_proc.attach("sh2", Default::default()).context("starting attach proc")?; - waiter.wait_event("daemon-bidi-stream-enter")?; - - let out = daemon_proc.detach(vec![String::from("sh1"), String::from("sh2")])?; - assert!(out.status.success(), "not successful"); - - let stderr = String::from_utf8_lossy(&out.stderr[..]); - assert_eq!(stderr.len(), 0, "expected no stderr"); - - let stdout = String::from_utf8_lossy(&out.stdout[..]); - assert_eq!(stdout.len(), 0, "expected no stdout"); - - waiter.wait_event("daemon-bidi-stream-done")?; - daemon_proc.events = Some(waiter.wait_final_event("daemon-bidi-stream-done")?); - - Ok(()) - }) + let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) + .context("starting daemon proc")?; + + let mut waiter = daemon_proc.events.take().unwrap().waiter([ + "daemon-bidi-stream-enter", + "daemon-bidi-stream-enter", + "daemon-bidi-stream-done", + "daemon-bidi-stream-done", + ]); + let _sess1 = daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; + waiter.wait_event("daemon-bidi-stream-enter")?; + + let _sess2 = daemon_proc.attach("sh2", Default::default()).context("starting attach proc")?; + waiter.wait_event("daemon-bidi-stream-enter")?; + + let out = daemon_proc.detach(vec![String::from("sh1"), String::from("sh2")])?; + assert!(out.status.success(), "not successful"); + + let stderr = String::from_utf8_lossy(&out.stderr[..]); + assert_eq!(stderr.len(), 0, "expected no stderr"); + + let stdout = String::from_utf8_lossy(&out.stdout[..]); + assert_eq!(stdout.len(), 0, "expected no stdout"); + + waiter.wait_event("daemon-bidi-stream-done")?; + daemon_proc.events = Some(waiter.wait_final_event("daemon-bidi-stream-done")?); + + Ok(()) } #[test] fn multiple_mixed() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) - .context("starting daemon proc")?; + let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) + .context("starting daemon proc")?; - let mut waiter = daemon_proc - .events - .take() - .unwrap() - .waiter(["daemon-bidi-stream-enter", "daemon-bidi-stream-done"]); - let _attach_proc = - daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; - waiter.wait_event("daemon-bidi-stream-enter")?; + let mut waiter = daemon_proc + .events + .take() + .unwrap() + .waiter(["daemon-bidi-stream-enter", "daemon-bidi-stream-done"]); + let _attach_proc = + daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; + waiter.wait_event("daemon-bidi-stream-enter")?; - let out = daemon_proc.detach(vec![String::from("sh1"), String::from("sh2")])?; - assert!(!out.status.success(), "unexpectedly successful"); + let out = daemon_proc.detach(vec![String::from("sh1"), String::from("sh2")])?; + assert!(!out.status.success(), "unexpectedly successful"); - let stdout = String::from_utf8_lossy(&out.stdout[..]); - assert_eq!(stdout.len(), 0, "expected no stdout"); + let stdout = String::from_utf8_lossy(&out.stdout[..]); + assert_eq!(stdout.len(), 0, "expected no stdout"); - let stderr = String::from_utf8_lossy(&out.stderr[..]); - assert!(stderr.contains("not found: sh2"), "expected not found"); + let stderr = String::from_utf8_lossy(&out.stderr[..]); + assert!(stderr.contains("not found: sh2"), "expected not found"); - daemon_proc.events = Some(waiter.wait_final_event("daemon-bidi-stream-done")?); + daemon_proc.events = Some(waiter.wait_final_event("daemon-bidi-stream-done")?); - Ok(()) - }) + Ok(()) } #[test] fn double_tap() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) - .context("starting daemon proc")?; + let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) + .context("starting daemon proc")?; - let mut waiter = daemon_proc - .events - .take() - .unwrap() - .waiter(["daemon-bidi-stream-enter", "daemon-bidi-stream-done"]); - let _attach_proc = - daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; - waiter.wait_event("daemon-bidi-stream-enter")?; + let mut waiter = daemon_proc + .events + .take() + .unwrap() + .waiter(["daemon-bidi-stream-enter", "daemon-bidi-stream-done"]); + let _attach_proc = + daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; + waiter.wait_event("daemon-bidi-stream-enter")?; - let out1 = daemon_proc.detach(vec![String::from("sh1")])?; - assert!(out1.status.success(), "not successful"); + let out1 = daemon_proc.detach(vec![String::from("sh1")])?; + assert!(out1.status.success(), "not successful"); - let stdout1 = String::from_utf8_lossy(&out1.stdout[..]); - assert_eq!(stdout1.len(), 0, "expected no stdout"); + let stdout1 = String::from_utf8_lossy(&out1.stdout[..]); + assert_eq!(stdout1.len(), 0, "expected no stdout"); - let stderr1 = String::from_utf8_lossy(&out1.stderr[..]); - assert_eq!(stderr1.len(), 0); + let stderr1 = String::from_utf8_lossy(&out1.stderr[..]); + assert_eq!(stderr1.len(), 0); - daemon_proc.events = Some(waiter.wait_final_event("daemon-bidi-stream-done")?); + daemon_proc.events = Some(waiter.wait_final_event("daemon-bidi-stream-done")?); - let out2 = daemon_proc.detach(vec![String::from("sh1")])?; - assert!(!out2.status.success(), "unexpectedly successful"); + let out2 = daemon_proc.detach(vec![String::from("sh1")])?; + assert!(!out2.status.success(), "unexpectedly successful"); - let stdout2 = String::from_utf8_lossy(&out2.stdout[..]); - assert_eq!(stdout2.len(), 0, "expected no stdout"); + let stdout2 = String::from_utf8_lossy(&out2.stdout[..]); + assert_eq!(stdout2.len(), 0, "expected no stdout"); - let stderr2 = String::from_utf8_lossy(&out2.stderr[..]); - assert!(stderr2.contains("not attached: sh1"), "expected not attached"); + let stderr2 = String::from_utf8_lossy(&out2.stderr[..]); + assert!(stderr2.contains("not attached: sh1"), "expected not attached"); - Ok(()) - }) + Ok(()) } diff --git a/shpool/tests/kill.rs b/shpool/tests/kill.rs index e0a233a0..6e0fc6b0 100644 --- a/shpool/tests/kill.rs +++ b/shpool/tests/kill.rs @@ -12,341 +12,313 @@ use crate::support::daemon::DaemonArgs; #[test] #[timeout(30000)] fn no_daemon() -> anyhow::Result<()> { - support::dump_err(|| { - let out = Command::new(support::shpool_bin()?) - .arg("--socket") - .arg("/fake/does/not/exist/shpool.socket") - .arg("--no-daemonize") - .arg("kill") - .output() - .context("spawning kill proc")?; - - assert!(!out.status.success(), "kill proc exited successfully"); - - let stderr = String::from_utf8_lossy(&out.stderr[..]); - assert!(stderr.contains("could not connect to daemon")); - - Ok(()) - }) + let out = Command::new(support::shpool_bin()?) + .arg("--socket") + .arg("/fake/does/not/exist/shpool.socket") + .arg("--no-daemonize") + .arg("kill") + .output() + .context("spawning kill proc")?; + + assert!(!out.status.success(), "kill proc exited successfully"); + + let stderr = String::from_utf8_lossy(&out.stderr[..]); + assert!(stderr.contains("could not connect to daemon")); + + Ok(()) } #[test] #[timeout(30000)] fn empty() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new( - "norc.toml", - DaemonArgs { listen_events: false, ..DaemonArgs::default() }, - ) - .context("starting daemon proc")?; + let mut daemon_proc = support::daemon::Proc::new( + "norc.toml", + DaemonArgs { listen_events: false, ..DaemonArgs::default() }, + ) + .context("starting daemon proc")?; - env::remove_var("SHPOOL_SESSION_NAME"); + env::remove_var("SHPOOL_SESSION_NAME"); - let out = daemon_proc.kill(vec![])?; - assert!(!out.status.success()); + let out = daemon_proc.kill(vec![])?; + assert!(!out.status.success()); - let stderr = String::from_utf8_lossy(&out.stderr[..]); - eprintln!("stderr: {stderr}"); - assert!(stderr.contains("no session to kill")); + let stderr = String::from_utf8_lossy(&out.stderr[..]); + eprintln!("stderr: {stderr}"); + assert!(stderr.contains("no session to kill")); - Ok(()) - }) + Ok(()) } #[test] #[timeout(30000)] fn version_mismatch_client_newer() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new( - "norc.toml", - DaemonArgs { - extra_env: vec![( - String::from("SHPOOL_TEST__OVERRIDE_VERSION"), - String::from("0.0.0"), - )], - ..DaemonArgs::default() - }, - ) - .context("starting daemon proc")?; + let mut daemon_proc = support::daemon::Proc::new( + "norc.toml", + DaemonArgs { + extra_env: vec![(String::from("SHPOOL_TEST__OVERRIDE_VERSION"), String::from("0.0.0"))], + ..DaemonArgs::default() + }, + ) + .context("starting daemon proc")?; - let waiter = daemon_proc.events.take().unwrap().waiter(["daemon-bidi-stream-enter"]); - let mut attach_proc = - daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; + let waiter = daemon_proc.events.take().unwrap().waiter(["daemon-bidi-stream-enter"]); + let mut attach_proc = + daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; - // get past the version mismatch prompt - attach_proc.run_cmd("")?; + // get past the version mismatch prompt + attach_proc.run_cmd("")?; - daemon_proc.events = Some(waiter.wait_final_event("daemon-bidi-stream-enter")?); + daemon_proc.events = Some(waiter.wait_final_event("daemon-bidi-stream-enter")?); - let out = daemon_proc.kill(vec![String::from("sh1")])?; - assert!(out.status.success()); + let out = daemon_proc.kill(vec![String::from("sh1")])?; + assert!(out.status.success()); - let stderr = String::from_utf8_lossy(&out.stderr[..]); - println!("stderr: {stderr}"); - assert!(stderr.contains("is newer")); - assert!(stderr.contains("try restarting")); + let stderr = String::from_utf8_lossy(&out.stderr[..]); + println!("stderr: {stderr}"); + assert!(stderr.contains("is newer")); + assert!(stderr.contains("try restarting")); - Ok(()) - }) + Ok(()) } #[test] #[timeout(30000)] fn single_attached() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) - .context("starting daemon proc")?; + let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) + .context("starting daemon proc")?; - let waiter = daemon_proc.events.take().unwrap().waiter(["daemon-bidi-stream-enter"]); - let _attach_proc = - daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; - daemon_proc.events = Some(waiter.wait_final_event("daemon-bidi-stream-enter")?); + let waiter = daemon_proc.events.take().unwrap().waiter(["daemon-bidi-stream-enter"]); + let _attach_proc = + daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; + daemon_proc.events = Some(waiter.wait_final_event("daemon-bidi-stream-enter")?); - let out = daemon_proc.kill(vec![String::from("sh1")])?; - assert!(out.status.success()); + let out = daemon_proc.kill(vec![String::from("sh1")])?; + assert!(out.status.success()); - let stdout = String::from_utf8_lossy(&out.stdout[..]); - assert!(stdout.is_empty()); + let stdout = String::from_utf8_lossy(&out.stdout[..]); + assert!(stdout.is_empty()); - let stderr = String::from_utf8_lossy(&out.stderr[..]); - assert!(stderr.is_empty()); + let stderr = String::from_utf8_lossy(&out.stderr[..]); + assert!(stderr.is_empty()); - Ok(()) - }) + Ok(()) } #[test] #[timeout(30000)] fn multiple_attached() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) - .context("starting daemon proc")?; - - let mut waiter = daemon_proc - .events - .take() - .unwrap() - .waiter(["daemon-bidi-stream-enter", "daemon-bidi-stream-enter"]); - let _sess1 = - daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; - let _sess2 = - daemon_proc.attach("sh2", Default::default()).context("starting attach proc")?; - waiter.wait_event("daemon-bidi-stream-enter")?; - daemon_proc.events = Some(waiter.wait_final_event("daemon-bidi-stream-enter")?); + let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) + .context("starting daemon proc")?; + + let mut waiter = daemon_proc + .events + .take() + .unwrap() + .waiter(["daemon-bidi-stream-enter", "daemon-bidi-stream-enter"]); + let _sess1 = daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; + let _sess2 = daemon_proc.attach("sh2", Default::default()).context("starting attach proc")?; + waiter.wait_event("daemon-bidi-stream-enter")?; + daemon_proc.events = Some(waiter.wait_final_event("daemon-bidi-stream-enter")?); - let out = daemon_proc.kill(vec![String::from("sh1"), String::from("sh2")])?; - assert!(out.status.success()); + let out = daemon_proc.kill(vec![String::from("sh1"), String::from("sh2")])?; + assert!(out.status.success()); - let stdout = String::from_utf8_lossy(&out.stdout[..]); - assert!(stdout.is_empty()); + let stdout = String::from_utf8_lossy(&out.stdout[..]); + assert!(stdout.is_empty()); - let stderr = String::from_utf8_lossy(&out.stderr[..]); - assert!(stderr.is_empty()); + let stderr = String::from_utf8_lossy(&out.stderr[..]); + assert!(stderr.is_empty()); - Ok(()) - }) + Ok(()) } #[test] #[timeout(30000)] fn reattach_after_kill() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) - .context("starting daemon proc")?; + let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) + .context("starting daemon proc")?; - let mut waiter = daemon_proc - .events - .take() - .unwrap() - .waiter(["daemon-handle-kill-removed-shells", "daemon-bidi-stream-done"]); + let mut waiter = daemon_proc + .events + .take() + .unwrap() + .waiter(["daemon-handle-kill-removed-shells", "daemon-bidi-stream-done"]); - let mut sess1 = - daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; - let mut lm1 = sess1.line_matcher()?; - sess1.run_cmd("export MYVAR=first")?; - sess1.run_cmd("echo $MYVAR")?; - lm1.scan_until_re("first$")?; + let mut sess1 = + daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; + let mut lm1 = sess1.line_matcher()?; + sess1.run_cmd("export MYVAR=first")?; + sess1.run_cmd("echo $MYVAR")?; + lm1.scan_until_re("first$")?; - let out = daemon_proc.kill(vec![String::from("sh1")])?; - assert!(out.status.success()); + let out = daemon_proc.kill(vec![String::from("sh1")])?; + assert!(out.status.success()); - let stdout = String::from_utf8_lossy(&out.stdout[..]); - assert!(stdout.is_empty()); + let stdout = String::from_utf8_lossy(&out.stdout[..]); + assert!(stdout.is_empty()); - let stderr = String::from_utf8_lossy(&out.stderr[..]); - assert!(stderr.is_empty()); + let stderr = String::from_utf8_lossy(&out.stderr[..]); + assert!(stderr.is_empty()); - waiter.wait_event("daemon-handle-kill-removed-shells")?; - waiter.wait_event("daemon-bidi-stream-done")?; + waiter.wait_event("daemon-handle-kill-removed-shells")?; + waiter.wait_event("daemon-bidi-stream-done")?; - let mut sess2 = - daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; - let mut lm2 = sess2.line_matcher()?; - sess2.run_cmd("echo ${MYVAR:-second}")?; - lm2.scan_until_re(".*second.*")?; + let mut sess2 = + daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; + let mut lm2 = sess2.line_matcher()?; + sess2.run_cmd("echo ${MYVAR:-second}")?; + lm2.scan_until_re(".*second.*")?; - Ok(()) - }) + Ok(()) } #[test] #[timeout(30000)] fn single_detached() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) - .context("starting daemon proc")?; - - let mut waiter = daemon_proc - .events - .take() - .unwrap() - .waiter(["daemon-bidi-stream-enter", "daemon-bidi-stream-done"]); - { - let _attach_proc = - daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; - waiter.wait_event("daemon-bidi-stream-enter")?; - } - daemon_proc.events = Some(waiter.wait_final_event("daemon-bidi-stream-done")?); - - let out = daemon_proc.kill(vec![String::from("sh1")])?; - assert!(out.status.success()); - - let stdout = String::from_utf8_lossy(&out.stdout[..]); - assert!(stdout.is_empty()); - - let stderr = String::from_utf8_lossy(&out.stderr[..]); - assert!(stderr.is_empty()); - - Ok(()) - }) -} + let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) + .context("starting daemon proc")?; -#[test] -#[timeout(30000)] -fn multiple_detached() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) - .context("starting daemon proc")?; - - let mut waiter = daemon_proc.events.take().unwrap().waiter([ - "daemon-bidi-stream-enter", - "daemon-bidi-stream-enter", - "daemon-bidi-stream-done", - "daemon-bidi-stream-done", - ]); - - { - let _sess1 = - daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; - let _sess2 = - daemon_proc.attach("sh2", Default::default()).context("starting attach proc")?; - waiter.wait_event("daemon-bidi-stream-enter")?; - waiter.wait_event("daemon-bidi-stream-enter")?; - } - waiter.wait_event("daemon-bidi-stream-done")?; - daemon_proc.events = Some(waiter.wait_final_event("daemon-bidi-stream-done")?); - - let out = daemon_proc.kill(vec![String::from("sh1"), String::from("sh2")])?; - assert!(out.status.success()); - - let stdout = String::from_utf8_lossy(&out.stdout[..]); - assert!(stdout.is_empty()); - - let stderr = String::from_utf8_lossy(&out.stderr[..]); - assert!(stderr.is_empty()); - - Ok(()) - }) + let mut waiter = daemon_proc + .events + .take() + .unwrap() + .waiter(["daemon-bidi-stream-enter", "daemon-bidi-stream-done"]); + { + let _attach_proc = + daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; + waiter.wait_event("daemon-bidi-stream-enter")?; + } + daemon_proc.events = Some(waiter.wait_final_event("daemon-bidi-stream-done")?); + + let out = daemon_proc.kill(vec![String::from("sh1")])?; + assert!(out.status.success()); + + let stdout = String::from_utf8_lossy(&out.stdout[..]); + assert!(stdout.is_empty()); + + let stderr = String::from_utf8_lossy(&out.stderr[..]); + assert!(stderr.is_empty()); + + Ok(()) } #[test] #[timeout(30000)] -fn multiple_mixed() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) - .context("starting daemon proc")?; - - let mut waiter = daemon_proc.events.take().unwrap().waiter([ - "daemon-bidi-stream-enter", - "daemon-bidi-stream-done", - "daemon-bidi-stream-enter", - ]); - - { - let _sess1 = - daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; - waiter.wait_event("daemon-bidi-stream-enter")?; - } +fn multiple_detached() -> anyhow::Result<()> { + let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) + .context("starting daemon proc")?; - waiter.wait_event("daemon-bidi-stream-done")?; + let mut waiter = daemon_proc.events.take().unwrap().waiter([ + "daemon-bidi-stream-enter", + "daemon-bidi-stream-enter", + "daemon-bidi-stream-done", + "daemon-bidi-stream-done", + ]); + { + let _sess1 = + daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; let _sess2 = daemon_proc.attach("sh2", Default::default()).context("starting attach proc")?; - daemon_proc.events = Some(waiter.wait_final_event("daemon-bidi-stream-enter")?); + waiter.wait_event("daemon-bidi-stream-enter")?; + waiter.wait_event("daemon-bidi-stream-enter")?; + } + waiter.wait_event("daemon-bidi-stream-done")?; + daemon_proc.events = Some(waiter.wait_final_event("daemon-bidi-stream-done")?); - let out = daemon_proc.kill(vec![String::from("sh1"), String::from("sh2")])?; - assert!(out.status.success()); + let out = daemon_proc.kill(vec![String::from("sh1"), String::from("sh2")])?; + assert!(out.status.success()); - let stdout = String::from_utf8_lossy(&out.stdout[..]); - assert!(stdout.is_empty()); + let stdout = String::from_utf8_lossy(&out.stdout[..]); + assert!(stdout.is_empty()); - let stderr = String::from_utf8_lossy(&out.stderr[..]); - assert!(stderr.is_empty()); + let stderr = String::from_utf8_lossy(&out.stderr[..]); + assert!(stderr.is_empty()); - Ok(()) - }) + Ok(()) } #[test] #[timeout(30000)] -fn running_env_var() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) - .context("starting daemon proc")?; - - let mut waiter = daemon_proc - .events - .take() - .unwrap() - .waiter(["daemon-bidi-stream-enter", "daemon-bidi-stream-done"]); - let _attach_proc = +fn multiple_mixed() -> anyhow::Result<()> { + let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) + .context("starting daemon proc")?; + + let mut waiter = daemon_proc.events.take().unwrap().waiter([ + "daemon-bidi-stream-enter", + "daemon-bidi-stream-done", + "daemon-bidi-stream-enter", + ]); + + { + let _sess1 = daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; waiter.wait_event("daemon-bidi-stream-enter")?; + } + + waiter.wait_event("daemon-bidi-stream-done")?; + + let _sess2 = daemon_proc.attach("sh2", Default::default()).context("starting attach proc")?; + daemon_proc.events = Some(waiter.wait_final_event("daemon-bidi-stream-enter")?); - let out = Command::new(support::shpool_bin()?) - .arg("--socket") - .arg(&daemon_proc.socket_path) - .arg("kill") - .env("SHPOOL_SESSION_NAME", "sh1") - .output() - .context("spawning detach cmd")?; - assert!(out.status.success(), "not successful"); + let out = daemon_proc.kill(vec![String::from("sh1"), String::from("sh2")])?; + assert!(out.status.success()); - let stderr = String::from_utf8_lossy(&out.stderr[..]); - assert_eq!(stderr.len(), 0, "expected no stderr"); + let stdout = String::from_utf8_lossy(&out.stdout[..]); + assert!(stdout.is_empty()); - let stdout = String::from_utf8_lossy(&out.stdout[..]); - assert_eq!(stdout.len(), 0, "expected no stdout"); + let stderr = String::from_utf8_lossy(&out.stderr[..]); + assert!(stderr.is_empty()); - daemon_proc.events = Some(waiter.wait_final_event("daemon-bidi-stream-done")?); + Ok(()) +} - Ok(()) - }) +#[test] +#[timeout(30000)] +fn running_env_var() -> anyhow::Result<()> { + let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) + .context("starting daemon proc")?; + + let mut waiter = daemon_proc + .events + .take() + .unwrap() + .waiter(["daemon-bidi-stream-enter", "daemon-bidi-stream-done"]); + let _attach_proc = + daemon_proc.attach("sh1", Default::default()).context("starting attach proc")?; + waiter.wait_event("daemon-bidi-stream-enter")?; + + let out = Command::new(support::shpool_bin()?) + .arg("--socket") + .arg(&daemon_proc.socket_path) + .arg("kill") + .env("SHPOOL_SESSION_NAME", "sh1") + .output() + .context("spawning detach cmd")?; + assert!(out.status.success(), "not successful"); + + let stderr = String::from_utf8_lossy(&out.stderr[..]); + assert_eq!(stderr.len(), 0, "expected no stderr"); + + let stdout = String::from_utf8_lossy(&out.stdout[..]); + assert_eq!(stdout.len(), 0, "expected no stdout"); + + daemon_proc.events = Some(waiter.wait_final_event("daemon-bidi-stream-done")?); + + Ok(()) } #[test] #[timeout(30000)] fn missing() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) - .context("starting daemon proc")?; + let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) + .context("starting daemon proc")?; - let out = daemon_proc.kill(vec![String::from("missing")])?; - assert!(!out.status.success()); + let out = daemon_proc.kill(vec![String::from("missing")])?; + assert!(!out.status.success()); - let stderr = String::from_utf8_lossy(&out.stderr[..]); - assert!(stderr.contains("not found: missing")); + let stderr = String::from_utf8_lossy(&out.stderr[..]); + assert!(stderr.contains("not found: missing")); - Ok(()) - }) + Ok(()) } diff --git a/shpool/tests/list.rs b/shpool/tests/list.rs index 9cb19374..7cd263e3 100644 --- a/shpool/tests/list.rs +++ b/shpool/tests/list.rs @@ -11,211 +11,193 @@ use crate::support::daemon::DaemonArgs; #[test] #[timeout(30000)] fn empty() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new( - "norc.toml", - DaemonArgs { listen_events: false, ..DaemonArgs::default() }, - ) - .context("starting daemon proc")?; - let out = daemon_proc.list()?; - assert!(out.status.success(), "list proc did not exit successfully"); - - let stderr = String::from_utf8_lossy(&out.stderr[..]); - assert_eq!(stderr.len(), 0, "expected no stderr"); - - let stdout = String::from_utf8_lossy(&out.stdout[..]); - assert!(stdout.contains("NAME")); - assert!(stdout.contains("STARTED_AT")); - - Ok(()) - }) + let mut daemon_proc = support::daemon::Proc::new( + "norc.toml", + DaemonArgs { listen_events: false, ..DaemonArgs::default() }, + ) + .context("starting daemon proc")?; + let out = daemon_proc.list()?; + assert!(out.status.success(), "list proc did not exit successfully"); + + let stderr = String::from_utf8_lossy(&out.stderr[..]); + assert_eq!(stderr.len(), 0, "expected no stderr"); + + let stdout = String::from_utf8_lossy(&out.stdout[..]); + assert!(stdout.contains("NAME")); + assert!(stdout.contains("STARTED_AT")); + + Ok(()) } #[test] #[timeout(30000)] fn version_mismatch_client_newer() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new( - "norc.toml", - DaemonArgs { - listen_events: false, - extra_env: vec![( - String::from("SHPOOL_TEST__OVERRIDE_VERSION"), - String::from("0.0.0"), - )], - ..Default::default() - }, - ) - .context("starting daemon proc")?; - let out = daemon_proc.list()?; - assert!(out.status.success(), "list proc did not exit successfully"); - - let stderr = String::from_utf8_lossy(&out.stderr[..]); - assert!(stderr.contains("is newer")); - assert!(stderr.contains("try restarting")); - - Ok(()) - }) + let mut daemon_proc = support::daemon::Proc::new( + "norc.toml", + DaemonArgs { + listen_events: false, + extra_env: vec![(String::from("SHPOOL_TEST__OVERRIDE_VERSION"), String::from("0.0.0"))], + ..Default::default() + }, + ) + .context("starting daemon proc")?; + let out = daemon_proc.list()?; + assert!(out.status.success(), "list proc did not exit successfully"); + + let stderr = String::from_utf8_lossy(&out.stderr[..]); + assert!(stderr.contains("is newer")); + assert!(stderr.contains("try restarting")); + + Ok(()) } #[test] #[timeout(30000)] fn version_mismatch_client_older() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new( - "norc.toml", - DaemonArgs { - listen_events: false, - extra_env: vec![( - String::from("SHPOOL_TEST__OVERRIDE_VERSION"), - String::from("99999.0.0"), - )], - ..Default::default() - }, - ) - .context("starting daemon proc")?; - let out = daemon_proc.list()?; - assert!(out.status.success(), "list proc did not exit successfully"); - - let stderr = String::from_utf8_lossy(&out.stderr[..]); - assert!(stderr.contains("is older")); - assert!(stderr.contains("try restarting")); - - Ok(()) - }) + let mut daemon_proc = support::daemon::Proc::new( + "norc.toml", + DaemonArgs { + listen_events: false, + extra_env: vec![( + String::from("SHPOOL_TEST__OVERRIDE_VERSION"), + String::from("99999.0.0"), + )], + ..Default::default() + }, + ) + .context("starting daemon proc")?; + let out = daemon_proc.list()?; + assert!(out.status.success(), "list proc did not exit successfully"); + + let stderr = String::from_utf8_lossy(&out.stderr[..]); + assert!(stderr.contains("is older")); + assert!(stderr.contains("try restarting")); + + Ok(()) } #[test] #[timeout(30000)] fn no_daemon() -> anyhow::Result<()> { - support::dump_err(|| { - let out = Command::new(support::shpool_bin()?) - .arg("--socket") - .arg("/fake/does/not/exist/shpool.socket") - .arg("--no-daemonize") - .arg("list") - .output() - .context("spawning list proc")?; + let out = Command::new(support::shpool_bin()?) + .arg("--socket") + .arg("/fake/does/not/exist/shpool.socket") + .arg("--no-daemonize") + .arg("list") + .output() + .context("spawning list proc")?; - assert!(!out.status.success(), "list proc exited successfully"); + assert!(!out.status.success(), "list proc exited successfully"); - let stderr = String::from_utf8_lossy(&out.stderr[..]); - assert!(stderr.contains("could not connect to daemon")); + let stderr = String::from_utf8_lossy(&out.stderr[..]); + assert!(stderr.contains("could not connect to daemon")); - Ok(()) - }) + Ok(()) } #[test] #[timeout(30000)] fn one_session() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) - .context("starting daemon proc")?; - let bidi_enter_w = daemon_proc.events.take().unwrap().waiter(["daemon-bidi-stream-enter"]); + let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) + .context("starting daemon proc")?; + let bidi_enter_w = daemon_proc.events.take().unwrap().waiter(["daemon-bidi-stream-enter"]); - let _sess1 = daemon_proc.attach("sh1", Default::default())?; + let _sess1 = daemon_proc.attach("sh1", Default::default())?; - daemon_proc.events = Some(bidi_enter_w.wait_final_event("daemon-bidi-stream-enter")?); + daemon_proc.events = Some(bidi_enter_w.wait_final_event("daemon-bidi-stream-enter")?); - let out = daemon_proc.list()?; - assert!(out.status.success(), "list proc did not exit successfully"); + let out = daemon_proc.list()?; + assert!(out.status.success(), "list proc did not exit successfully"); - let stderr = String::from_utf8_lossy(&out.stderr[..]); - assert_eq!(stderr.len(), 0, "expected no stderr"); + let stderr = String::from_utf8_lossy(&out.stderr[..]); + assert_eq!(stderr.len(), 0, "expected no stderr"); - let stdout = String::from_utf8_lossy(&out.stdout[..]); - assert!(stdout.contains("sh1")); + let stdout = String::from_utf8_lossy(&out.stdout[..]); + assert!(stdout.contains("sh1")); - Ok(()) - }) + Ok(()) } #[test] #[timeout(30000)] fn two_sessions() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) - .context("starting daemon proc")?; - let mut bidi_enter_w = daemon_proc.events.take().unwrap().waiter([ - "daemon-bidi-stream-enter", - "daemon-bidi-stream-enter", - "daemon-bidi-stream-done", - ]); + let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) + .context("starting daemon proc")?; + let mut bidi_enter_w = daemon_proc.events.take().unwrap().waiter([ + "daemon-bidi-stream-enter", + "daemon-bidi-stream-enter", + "daemon-bidi-stream-done", + ]); - let _sess1 = daemon_proc.attach("sh1", Default::default())?; + let _sess1 = daemon_proc.attach("sh1", Default::default())?; - bidi_enter_w.wait_event("daemon-bidi-stream-enter")?; + bidi_enter_w.wait_event("daemon-bidi-stream-enter")?; - { - let _sess2 = daemon_proc.attach("sh2", Default::default())?; + { + let _sess2 = daemon_proc.attach("sh2", Default::default())?; - bidi_enter_w.wait_event("daemon-bidi-stream-enter")?; + bidi_enter_w.wait_event("daemon-bidi-stream-enter")?; - let out = daemon_proc.list()?; - assert!(out.status.success(), "list proc did not exit successfully"); + let out = daemon_proc.list()?; + assert!(out.status.success(), "list proc did not exit successfully"); - let stderr = String::from_utf8_lossy(&out.stderr[..]); - assert_eq!(stderr.len(), 0, "expected no stderr"); + let stderr = String::from_utf8_lossy(&out.stderr[..]); + assert_eq!(stderr.len(), 0, "expected no stderr"); - let stdout = String::from_utf8_lossy(&out.stdout[..]); - assert!(stdout.contains("sh1")); - assert!(stdout.contains("sh2")); - } + let stdout = String::from_utf8_lossy(&out.stdout[..]); + assert!(stdout.contains("sh1")); + assert!(stdout.contains("sh2")); + } - // wait for the hangup to complete - bidi_enter_w.wait_event("daemon-bidi-stream-done")?; + // wait for the hangup to complete + bidi_enter_w.wait_event("daemon-bidi-stream-done")?; - let out = daemon_proc.list()?; - assert!(out.status.success(), "list proc did not exit successfully"); + let out = daemon_proc.list()?; + assert!(out.status.success(), "list proc did not exit successfully"); - let sh1_re = Regex::new("sh1.*attached")?; - let sh2_re = Regex::new("sh2.*disconnected")?; - let stdout = String::from_utf8_lossy(&out.stdout[..]); - dbg!(&stdout); - assert!(sh1_re.is_match(&stdout)); - assert!(sh2_re.is_match(&stdout)); + let sh1_re = Regex::new("sh1.*attached")?; + let sh2_re = Regex::new("sh2.*disconnected")?; + let stdout = String::from_utf8_lossy(&out.stdout[..]); + dbg!(&stdout); + assert!(sh1_re.is_match(&stdout)); + assert!(sh2_re.is_match(&stdout)); - Ok(()) - }) + Ok(()) } #[test] #[timeout(30000)] fn json_output() -> anyhow::Result<()> { - support::dump_err(|| { - let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) - .context("starting daemon proc")?; - let bidi_enter_w = daemon_proc.events.take().unwrap().waiter(["daemon-bidi-stream-enter"]); + let mut daemon_proc = support::daemon::Proc::new("norc.toml", DaemonArgs::default()) + .context("starting daemon proc")?; + let bidi_enter_w = daemon_proc.events.take().unwrap().waiter(["daemon-bidi-stream-enter"]); - let _sess1 = daemon_proc.attach("sh1", Default::default())?; + let _sess1 = daemon_proc.attach("sh1", Default::default())?; - daemon_proc.events = Some(bidi_enter_w.wait_final_event("daemon-bidi-stream-enter")?); + daemon_proc.events = Some(bidi_enter_w.wait_final_event("daemon-bidi-stream-enter")?); - let out = daemon_proc.list_json()?; - assert!(out.status.success(), "list --json proc did not exit successfully"); + let out = daemon_proc.list_json()?; + assert!(out.status.success(), "list --json proc did not exit successfully"); - let stderr = String::from_utf8_lossy(&out.stderr[..]); - assert_eq!(stderr.len(), 0, "expected no stderr"); + let stderr = String::from_utf8_lossy(&out.stderr[..]); + assert_eq!(stderr.len(), 0, "expected no stderr"); - let stdout = String::from_utf8_lossy(&out.stdout[..]); - let parsed: serde_json::Value = - serde_json::from_str(&stdout).context("parsing JSON output")?; + let stdout = String::from_utf8_lossy(&out.stdout[..]); + let parsed: serde_json::Value = serde_json::from_str(&stdout).context("parsing JSON output")?; - let sessions = parsed - .get("sessions") - .ok_or_else(|| anyhow!("missing 'sessions' field in JSON output"))? - .as_array() - .ok_or_else(|| anyhow!("'sessions' is not an array"))?; + let sessions = parsed + .get("sessions") + .ok_or_else(|| anyhow!("missing 'sessions' field in JSON output"))? + .as_array() + .ok_or_else(|| anyhow!("'sessions' is not an array"))?; - assert!(!sessions.is_empty(), "expected at least one session"); + assert!(!sessions.is_empty(), "expected at least one session"); - let first_session = &sessions[0]; - assert!( - first_session.get("last_connected_at_unix_ms").is_some(), - "missing 'last_connected_at_unix_ms' field" - ); + let first_session = &sessions[0]; + assert!( + first_session.get("last_connected_at_unix_ms").is_some(), + "missing 'last_connected_at_unix_ms' field" + ); - Ok(()) - }) + Ok(()) } diff --git a/shpool/tests/support/mod.rs b/shpool/tests/support/mod.rs index 7bde5e13..becd4457 100644 --- a/shpool/tests/support/mod.rs +++ b/shpool/tests/support/mod.rs @@ -20,14 +20,6 @@ pub mod events; pub mod line_matcher; pub mod tmpdir; -pub fn dump_err(f: fn() -> anyhow::Result<()>) -> anyhow::Result<()> { - let res = f(); - if let Err(e) = res.as_ref() { - eprintln!("top level error: {e:?}"); - } - res -} - pub fn testdata_file>(file: P) -> PathBuf { let mut dir = cargo_dir(); dir.pop();