diff options
-rw-r--r-- | src/channel.rs | 9 | ||||
-rw-r--r-- | tests/all/channel.rs | 29 |
2 files changed, 33 insertions, 5 deletions
diff --git a/src/channel.rs b/src/channel.rs index 03bbba0..7086f5d 100644 --- a/src/channel.rs +++ b/src/channel.rs @@ -328,7 +328,10 @@ impl Channel { self.read_limit = Some(limit); } - /// Check if the remote host has sent an EOF status for the selected stream. + /// Check if the remote host has sent an EOF status for the channel. + /// Take care: the EOF status is for the entire channel which can be confusing + /// because the reading from the channel reads only the stdout stream. + /// unread, buffered, stderr data will cause eof() to return false. pub fn eof(&self) -> bool { self.read_limit == Some(0) || unsafe { raw::libssh2_channel_eof(self.raw) != 0 } } @@ -342,6 +345,10 @@ impl Channel { } /// Wait for the remote end to send EOF. + /// Note that unread buffered stdout and stderr will cause this function + /// to return `Ok(())` without waiting. + /// You should call the eof() function after calling this to check the + /// status of the channel. pub fn wait_eof(&mut self) -> Result<(), Error> { unsafe { self.sess.rc(raw::libssh2_channel_wait_eof(self.raw)) } } diff --git a/tests/all/channel.rs b/tests/all/channel.rs index 2a9dfdf..9053cf0 100644 --- a/tests/all/channel.rs +++ b/tests/all/channel.rs @@ -1,15 +1,33 @@ +use ssh2::Channel; use std::io::prelude::*; use std::net::{TcpListener, TcpStream}; use std::thread; +/// Consume all available stdout and stderr data. +/// It is important to read both if you are using +/// channel.eof() to make assertions that the stream +/// is complete +fn consume_stdio(channel: &mut Channel) -> (String, String) { + let mut stdout = String::new(); + channel.read_to_string(&mut stdout).unwrap(); + + let mut stderr = String::new(); + channel.stderr().read_to_string(&mut stderr).unwrap(); + + (stdout, stderr) +} + #[test] fn smoke() { let sess = ::authed_session(); let mut channel = sess.channel_session().unwrap(); channel.flush().unwrap(); channel.exec("true").unwrap(); + consume_stdio(&mut channel); + channel.wait_eof().unwrap(); assert!(channel.eof()); + channel.close().unwrap(); channel.wait_close().unwrap(); assert_eq!(channel.exit_status().unwrap(), 0); @@ -22,8 +40,11 @@ fn bad_smoke() { let mut channel = sess.channel_session().unwrap(); channel.flush().unwrap(); channel.exec("false").unwrap(); + consume_stdio(&mut channel); + channel.wait_eof().unwrap(); assert!(channel.eof()); + channel.close().unwrap(); channel.wait_close().unwrap(); assert_eq!(channel.exit_status().unwrap(), 1); @@ -35,8 +56,8 @@ fn reading_data() { let sess = ::authed_session(); let mut channel = sess.channel_session().unwrap(); channel.exec("echo foo").unwrap(); - let mut output = String::new(); - channel.read_to_string(&mut output).unwrap(); + + let (output, _) = consume_stdio(&mut channel); assert_eq!(output, "foo\n"); } @@ -46,8 +67,8 @@ fn writing_data() { let mut channel = sess.channel_session().unwrap(); channel.exec("read foo && echo $foo").unwrap(); channel.write_all(b"foo\n").unwrap(); - let mut output = String::new(); - channel.read_to_string(&mut output).unwrap(); + + let (output, _) = consume_stdio(&mut channel); assert_eq!(output, "foo\n"); } |