summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/channel.rs9
-rw-r--r--tests/all/channel.rs29
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");
}