add unittest for shell cmd executor
This commit is contained in:
@ -6,6 +6,7 @@ use satrs::{
|
||||
request::{GenericMessage, MessageMetadata},
|
||||
res_code::ResultU16,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{
|
||||
env::temp_dir,
|
||||
path::{Path, PathBuf},
|
||||
@ -21,6 +22,12 @@ use ops_sat_rs::config::{
|
||||
|
||||
use crate::requests::CompositeRequest;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct ShellCmd {
|
||||
cmd: String,
|
||||
args: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, TryFromPrimitive)]
|
||||
#[repr(u32)]
|
||||
pub enum ActionId {
|
||||
@ -139,14 +146,18 @@ impl ExperimentController {
|
||||
action_req: &ActionRequest,
|
||||
) {
|
||||
if let ActionRequestVariant::VecData(data) = &action_req.variant {
|
||||
match String::from_utf8(data.to_vec()) {
|
||||
Ok(cmd_str) => {
|
||||
log::info!("executing command: {}", cmd_str);
|
||||
match Command::new(cmd_str).status() {
|
||||
let shell_cmd_result: serde_json::Result<ShellCmd> = serde_json::from_slice(data);
|
||||
match shell_cmd_result {
|
||||
Ok(shell_cmd) => {
|
||||
log::info!("executing shell cmd {:?}", shell_cmd);
|
||||
println!("executing shell cmd {:?}", shell_cmd);
|
||||
match Command::new(shell_cmd.cmd).args(shell_cmd.args).status() {
|
||||
Ok(status) => {
|
||||
if status.success() {
|
||||
println!("cmd exec success");
|
||||
self.send_completion_success(requestor, action_req);
|
||||
} else {
|
||||
println!("cmd exec failed with {}", status);
|
||||
log::warn!("execution of command failed: {}", status);
|
||||
self.send_completion_failure(
|
||||
requestor,
|
||||
@ -158,6 +169,7 @@ impl ExperimentController {
|
||||
}
|
||||
Err(e) => {
|
||||
log::warn!("execution of command failed with IO error: {}", e);
|
||||
println!("cmd exec failed with {}", e);
|
||||
self.send_completion_failure(
|
||||
requestor,
|
||||
action_req,
|
||||
@ -168,15 +180,12 @@ impl ExperimentController {
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
log::warn!("invalid utf-8 data in action request: {}", e);
|
||||
self.send_completion_failure(
|
||||
requestor,
|
||||
action_req,
|
||||
SHELL_CMD_INVALID_FORMAT,
|
||||
Some(e.to_string().into()),
|
||||
);
|
||||
log::warn!("failed to deserialize shell command: {}", e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log::warn!("no shell command was supplied for shell command action command");
|
||||
self.send_completion_failure(requestor, action_req, SHELL_CMD_INVALID_FORMAT, None);
|
||||
}
|
||||
}
|
||||
|
||||
@ -204,3 +213,60 @@ impl ExperimentController {
|
||||
check_at_path(self.home_path_stop_file.as_path());
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::sync::{mpsc, Arc};
|
||||
|
||||
use tempfile::NamedTempFile;
|
||||
|
||||
use super::*;
|
||||
|
||||
fn init() {
|
||||
env_logger::builder().is_test(true).init();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_shell_cmd_exection() {
|
||||
init();
|
||||
let (composite_req_tx, composite_req_rx) = mpsc::channel();
|
||||
let (action_reply_tx, action_reply_rx) = mpsc::channel();
|
||||
let stop_signal = Arc::default();
|
||||
let mut exp_ctrl =
|
||||
ExperimentController::new(composite_req_rx, action_reply_tx, stop_signal);
|
||||
let named_temp_file = NamedTempFile::new().expect("creating temp file failed");
|
||||
let cmd = ShellCmd {
|
||||
cmd: "rm".to_string(),
|
||||
args: vec![named_temp_file.path().to_string_lossy().to_string()],
|
||||
};
|
||||
let cmd_serialized = serde_json::to_string(&cmd).expect("serialization failed");
|
||||
let action_req = satrs::action::ActionRequest {
|
||||
action_id: ActionId::ExecuteShellCommandBlocking as u32,
|
||||
variant: satrs::action::ActionRequestVariant::VecData(cmd_serialized.into_bytes()),
|
||||
};
|
||||
composite_req_tx
|
||||
.send(GenericMessage::new(
|
||||
MessageMetadata::new(1, 2),
|
||||
CompositeRequest::Action(action_req),
|
||||
))
|
||||
.expect("sending action request failed");
|
||||
exp_ctrl.perform_operation();
|
||||
assert!(!named_temp_file.path().exists());
|
||||
let action_reply = action_reply_rx
|
||||
.try_recv()
|
||||
.expect("receiving action reply failed");
|
||||
assert_eq!(
|
||||
action_reply.message.action_id,
|
||||
ActionId::ExecuteShellCommandBlocking as u32
|
||||
);
|
||||
match action_reply.message.variant {
|
||||
ActionReplyVariant::Completed => (),
|
||||
_ => {
|
||||
panic!(
|
||||
"unexecpted action reply variant {:?}",
|
||||
action_reply.message.variant
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user