use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
pub(crate) const DEFAULT_CHECK_PROCESS_TAIL_LINES: usize = 50;
#[derive(Debug, Deserialize, Serialize, JsonSchema)]
pub struct ExecParams {
pub command: String,
#[serde(default)]
pub background: bool,
pub timeout_ms: Option<u64>,
pub log_path: Option<String>,
}
#[derive(Debug, Deserialize, Serialize, JsonSchema)]
pub struct SudoExecParams {
pub command: String,
#[serde(default)]
pub background: bool,
pub timeout_ms: Option<u64>,
pub log_path: Option<String>,
}
#[derive(Debug, Deserialize, Serialize, JsonSchema)]
pub struct CheckProcessParams {
pub job_id: String,
#[serde(default = "default_tail_lines")]
pub tail_lines: usize,
}
#[derive(Debug, Deserialize, Serialize, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct ApplyPatchParams {
pub patch: String,
}
fn default_tail_lines() -> usize {
DEFAULT_CHECK_PROCESS_TAIL_LINES
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_exec_params_deserialize() {
let json = r#"{"command": "echo hello"}"#;
let params: ExecParams = serde_json::from_str(json).unwrap();
assert_eq!(params.command, "echo hello");
assert!(!params.background);
assert!(params.timeout_ms.is_none());
assert!(params.log_path.is_none());
}
#[test]
fn test_exec_params_deserialize_background() {
let json = r#"{"command": "sleep 10", "background": true, "timeout_ms": 1000, "log_path": "/tmp/x.log"}"#;
let params: ExecParams = serde_json::from_str(json).unwrap();
assert_eq!(params.command, "sleep 10");
assert!(params.background);
assert_eq!(params.timeout_ms, Some(1000));
assert_eq!(params.log_path.as_deref(), Some("/tmp/x.log"));
}
#[test]
fn test_sudo_exec_params_deserialize() {
let json = r#"{"command": "apt update"}"#;
let params: SudoExecParams = serde_json::from_str(json).unwrap();
assert_eq!(params.command, "apt update");
assert!(!params.background);
assert!(params.timeout_ms.is_none());
assert!(params.log_path.is_none());
}
#[test]
fn test_check_process_params_deserialize() {
let json = r#"{"job_id": "job-123"}"#;
let params: CheckProcessParams = serde_json::from_str(json).unwrap();
assert_eq!(params.job_id, "job-123");
assert_eq!(params.tail_lines, 50);
}
#[test]
fn test_check_process_params_with_tail_lines() {
let json = r#"{"job_id": "job-123", "tail_lines": 100}"#;
let params: CheckProcessParams = serde_json::from_str(json).unwrap();
assert_eq!(params.job_id, "job-123");
assert_eq!(params.tail_lines, 100);
}
#[test]
fn test_apply_patch_params_deserialize_and_reject_unknown_fields() {
let json = r#"{"patch":"*** Begin Patch\n*** Delete File: /tmp/old\n*** End Patch"}"#;
let params: ApplyPatchParams = serde_json::from_str(json).unwrap();
assert!(params.patch.contains("*** Delete File"));
let err =
serde_json::from_str::<ApplyPatchParams>(r#"{"patch":"x","remote_path":"/tmp/x"}"#)
.unwrap_err();
assert!(err.to_string().contains("unknown field `remote_path`"));
}
}