use serde_json::{self, Value};
use std::collections::HashMap;
use std::path::Path;
use std::process::Command;
use crate::error::NazaraResult;
use crate::{NazaraError, info};
pub fn execute(path: Option<String>) -> NazaraResult<HashMap<String, Value>> {
let script_path = match path.as_deref() {
Some(p) => Path::new(p),
None => {
info!("No plugin path provided. Custom field parameters ignored.");
return Ok(HashMap::new());
}
};
println!(
"Attempting to execute plugin at path '{}'...",
script_path.display()
);
if !script_path.is_file() {
return Err("Provided path does not lead to a file.".into());
}
let output = Command::new("bash").arg(script_path).output()?;
if !output.status.success() {
return Err(NazaraError::PluginExecution(
"Either you have a syntax error in your code or the file does not exist.".to_string(),
));
}
let stdout_str = String::from_utf8(output.stdout)?;
validate(&stdout_str)?;
Ok(serde_json::from_str(&stdout_str)?)
}
fn validate(output: &str) -> NazaraResult<()> {
serde_json::from_str::<Value>(output)
.map(|_| ())
.map_err(NazaraError::InvalidPluginOutput)
}
#[cfg(test)]
mod tests {
use std::error::Error;
use std::fs::File;
use std::io::Write;
use std::os::unix::fs::PermissionsExt;
use std::path::PathBuf;
use super::*;
fn create_test_script(content: &str) -> Result<PathBuf, Box<dyn Error>> {
let mut path = std::env::temp_dir();
path.push("test_script.sh");
let mut file = File::create(&path)?;
writeln!(file, "{content}")?;
#[cfg(unix)]
std::fs::set_permissions(&path, std::fs::Permissions::from_mode(0o755))?;
Ok(path)
}
#[test]
fn test_validate_invalid_json() {
let invalid_json = "Invalid JSON format";
let result = validate(invalid_json);
assert!(result.is_err());
if let Err(NazaraError::InvalidPluginOutput(e)) = result {
let error_message = e.to_string();
assert!(
error_message.contains("expected value")
|| error_message.contains("trailing characters")
);
}
}
#[test]
fn test_execute_invalid_json() {
let script_content = r#"
#!/bin/bash
echo "Invalid JSON"
"#;
let path = create_test_script(script_content).unwrap();
let result = execute(Some(path.to_str().unwrap().to_string()));
assert!(result.is_err());
if let Err(e) = result {
let error_message = e.to_string();
assert!(
error_message.contains("expected value")
|| error_message.contains("trailing characters")
);
}
}
}