|
@@ -10,7 +10,10 @@ use log::{error};
|
|
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
|
pub enum Message {
|
|
|
+ /// An echo request. This should elicit an identical reply.
|
|
|
Echo(String),
|
|
|
+ /// Orders the node to halt.
|
|
|
+ Halt,
|
|
|
}
|
|
|
|
|
|
pub struct Node {
|
|
@@ -38,14 +41,11 @@ impl Node {
|
|
|
Err(_) => break,
|
|
|
}
|
|
|
},
|
|
|
- // Break if the child is dead.
|
|
|
+ // Break if the child is has exited.
|
|
|
Err(serde_block_tree::Error::Eof) => break,
|
|
|
Err(serde_block_tree::Error::Io(io_err)) => {
|
|
|
match io_err.kind() {
|
|
|
- std::io::ErrorKind::UnexpectedEof => {
|
|
|
- error!("The child process closed its stdout stream.");
|
|
|
- break;
|
|
|
- }
|
|
|
+ std::io::ErrorKind::UnexpectedEof => break,
|
|
|
_ => error!("IO error ocurred: {:?}", io_err),
|
|
|
}
|
|
|
},
|
|
@@ -70,6 +70,30 @@ impl Node {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ pub fn halt(mut self) -> Result<(), NodeHaltError> {
|
|
|
+ self.send(&Message::Halt).unwrap();
|
|
|
+ match self.child.wait() {
|
|
|
+ Ok(status) => {
|
|
|
+ let code = status.code();
|
|
|
+ if code == Some(0) {
|
|
|
+ Ok(())
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ Err(NodeHaltError::NonZeroExitCode(code))
|
|
|
+ }
|
|
|
+ },
|
|
|
+ Err(err) => Err(NodeHaltError::Io(err)),
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#[derive(Debug)]
|
|
|
+pub enum NodeHaltError {
|
|
|
+ /// The node exited with a non-zero or non-existent status code.
|
|
|
+ NonZeroExitCode(Option<i32>),
|
|
|
+ /// An IO error was encountered.
|
|
|
+ Io(std::io::Error),
|
|
|
}
|
|
|
|
|
|
impl Drop for Node {
|
|
@@ -105,9 +129,16 @@ mod test {
|
|
|
node.send(&Message::Echo(expected.clone())).unwrap();
|
|
|
let reply = node.receive(Duration::from_millis(100)).unwrap();
|
|
|
let reply_payload = match reply {
|
|
|
- Message::Echo(actual) => actual,
|
|
|
+ Message::Echo(actual) => Some(actual),
|
|
|
+ _ => None,
|
|
|
};
|
|
|
- assert_eq!(expected, reply_payload.as_str());
|
|
|
+ assert_eq!(Some(expected), reply_payload);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ fn message_halt() {
|
|
|
+ let node = Node::new().unwrap();
|
|
|
+ node.halt().unwrap();
|
|
|
+ }
|
|
|
}
|