use std::sync::Arc;
use crate::{DriverCall, DriverCallback, DriverContext, DriverError, DriverResult, get_driver_by_name};
use serde_json::Value;
#[derive(Debug, Clone)]
pub struct Executor;
impl Executor {
pub fn new() -> Self {
Self
}
pub fn parse_driver_call(&self, json_str: &str) -> DriverResult<DriverCall> {
serde_json::from_str(json_str).map_err(|e| DriverError::Internal { message: format!("Failed to parse JSON: {}", e) })
}
pub fn parse_driver_call_from_value(&self, json_value: &Value) -> DriverResult<DriverCall> {
serde_json::from_value(json_value.clone()).map_err(|e| DriverError::Internal { message: format!("Failed to parse JSON value: {}", e) })
}
pub async fn execute(&self, call: &DriverCall, callback: Option<&dyn DriverCallback>, context: Option<&DriverContext>) -> DriverResult<String> {
let driver = get_driver_by_name(&call.action).ok_or_else(|| DriverError::DriverNotFound { name: call.action.clone() })?;
driver.execute(&call.parameters, callback, context).await
}
}
impl Default for Executor {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use std::collections::HashMap;
use super::*;
use serde_json::json;
#[tokio::test]
async fn test_parse_driver_call() {
let executor = Executor::new();
let json_str = r#"{"action": "test_action", "parameters": {"key": "value"}}"#;
let call = executor.parse_driver_call(json_str).unwrap();
assert_eq!(call.action, "test_action");
assert_eq!(call.parameters.get("key").unwrap().as_str(), Some("value"));
}
#[tokio::test]
async fn test_parse_driver_call_without_parameters() {
let executor = Executor::new();
let json_str = r#"{"action": "test_action"}"#;
let call = executor.parse_driver_call(json_str).unwrap();
assert_eq!(call.action, "test_action");
assert!(call.parameters.is_empty());
}
#[tokio::test]
async fn test_parse_driver_call_from_value() {
let executor = Executor::new();
let json_value = json!({
"action": "test_action",
"parameters": {
"key": "value"
}
});
let call = executor.parse_driver_call_from_value(&json_value).unwrap();
assert_eq!(call.action, "test_action");
assert_eq!(call.parameters.get("key").unwrap().as_str(), Some("value"));
}
#[tokio::test]
async fn test_parse_driver_call_from_value_without_parameters() {
let executor = Executor::new();
let json_value = json!({
"action": "test_action"
});
let call = executor.parse_driver_call_from_value(&json_value).unwrap();
assert_eq!(call.action, "test_action");
assert!(call.parameters.is_empty());
}
#[tokio::test]
async fn test_invalid_json_parse() {
let executor = Executor::new();
let invalid_json = "not a json";
let result = executor.parse_driver_call(invalid_json);
assert!(result.is_err());
match result {
Err(DriverError::Internal { message }) => {
assert!(message.contains("Failed to parse JSON"));
}
_ => panic!("Expected Internal error"),
}
}
#[tokio::test]
async fn test_driver_not_found() {
let executor = Executor::new();
let call = DriverCall { action: "nonexistent_driver".to_string(), parameters: HashMap::new() };
let result = executor.execute(&call, None, None).await;
assert!(result.is_err());
match result {
Err(DriverError::DriverNotFound { name }) => {
assert_eq!(name, "nonexistent_driver");
}
_ => panic!("Expected DriverNotFound error"),
}
}
}